Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Unified Diff: runtime/vm/clustered_snapshot.cc

Issue 2032153003: Use clustered serialization for full snapshots. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: round2 Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/clustered_snapshot.h ('k') | runtime/vm/dart.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/clustered_snapshot.cc
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e938fefb454842f7c627ec3fd11427386bbb16ef
--- /dev/null
+++ b/runtime/vm/clustered_snapshot.cc
@@ -0,0 +1,4998 @@
+// 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/class_finalizer.h"
+#include "vm/dart.h"
+#include "vm/dart_entry.h"
+#include "vm/exceptions.h"
+#include "vm/heap.h"
+#include "vm/lockers.h"
+#include "vm/longjump.h"
+#include "vm/native_entry.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/stub_code.h"
+#include "vm/symbols.h"
+#include "vm/timeline.h"
+#include "vm/version.h"
+
+namespace dart {
+
+static RawObject* AllocateUninitialized(PageSpace* old_space, intptr_t size) {
+ ASSERT(Utils::IsAligned(size, kObjectAlignment));
+ uword address = old_space->TryAllocateDataBumpLocked(size,
+ PageSpace::kForceGrowth);
+ if (address == 0) {
+ FATAL("Out of memory");
+ }
+ return reinterpret_cast<RawObject*>(address + kHeapObjectTag);
+}
+
+
+void Deserializer::InitializeHeader(RawObject* raw,
+ intptr_t class_id,
+ intptr_t size,
+ bool is_vm_isolate,
+ bool is_canonical) {
+ ASSERT(Utils::IsAligned(size, kObjectAlignment));
+ uword tags = 0;
+ tags = RawObject::ClassIdTag::update(class_id, tags);
+ tags = RawObject::SizeTag::update(size, tags);
+ tags = RawObject::VMHeapObjectTag::update(is_vm_isolate, tags);
+ tags = RawObject::CanonicalObjectTag::update(is_canonical, tags);
+ raw->ptr()->tags_ = tags;
+}
+
+
+class ClassSerializationCluster : public SerializationCluster {
+ public:
+ explicit ClassSerializationCluster(intptr_t num_cids) :
+ predefined_(kNumPredefinedCids), objects_(num_cids) { }
+ virtual ~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);
+ }
+
+ RawObject** from = cls->from();
+ RawObject** to = cls->to_snapshot(s->kind());
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kClassCid);
+ intptr_t count = predefined_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawClass* cls = predefined_[i];
+ intptr_t class_id = cls->ptr()->id_;
+ s->Write<intptr_t>(class_id);
+ s->AssignRef(cls);
+ }
+ count = objects_.length();
+ s->Write<intptr_t>(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) {
+ Snapshot::Kind kind = s->kind();
+ RawObject** from = cls->from();
+ RawObject** to = cls->to_snapshot(kind);
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ intptr_t class_id = cls->ptr()->id_;
+ s->WriteCid(class_id);
+ 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()->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_;
+};
+
+
+class ClassDeserializationCluster : public DeserializationCluster {
+ public:
+ ClassDeserializationCluster() { }
+ virtual ~ClassDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ predefined_start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ ClassTable* table = d->isolate()->class_table();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t class_id = d->Read<intptr_t>();
+ 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->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ Class::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ Snapshot::Kind kind = d->kind();
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+ 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));
+ RawObject** from = cls->from();
+ RawObject** to_snapshot = cls->to_snapshot(kind);
+ for (RawObject** p = from; p <= to_snapshot; p++) {
+ *p = d->ReadRef();
+ }
+
+ intptr_t class_id = d->ReadCid();
+ cls->ptr()->id_ = class_id;
+ 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()->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(),
+ is_vm_object);
+ RawObject** from = cls->from();
+ RawObject** to_snapshot = cls->to_snapshot(kind);
+ RawObject** to = cls->to();
+ for (RawObject** p = from; p <= to_snapshot; p++) {
+ *p = d->ReadRef();
+ }
+ for (RawObject** p = to_snapshot + 1; p <= to; p++) {
+ *p = Object::null();
+ }
+
+ intptr_t class_id = d->ReadCid();
+
+ ASSERT(class_id >= kNumPredefinedCids);
+ Instance fake;
+ cls->ptr()->handle_vtable_ = fake.vtable();
+
+ cls->ptr()->id_ = class_id;
+ 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()->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);
+ }
+ }
+
+ void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
+ NOT_IN_PRODUCT(TimelineDurationScope tds(Thread::Current(),
+ Timeline::GetIsolateStream(), "PostLoadClass"));
+
+ Class& cls = Class::Handle(zone);
+ for (intptr_t i = predefined_start_index_;
+ i < predefined_stop_index_;
+ i++) {
+ cls ^= refs.At(i);
+ cls.RehashConstants(zone);
+ }
+ for (intptr_t i = start_index_; i < stop_index_; i++) {
+ cls ^= refs.At(i);
+ cls.RehashConstants(zone);
+ }
+ }
+
+ private:
+ intptr_t predefined_start_index_;
+ intptr_t predefined_stop_index_;
+};
+
+
+class UnresolvedClassSerializationCluster : public SerializationCluster {
+ public:
+ UnresolvedClassSerializationCluster() { }
+ virtual ~UnresolvedClassSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawUnresolvedClass* cls = UnresolvedClass::RawCast(object);
+ objects_.Add(cls);
+
+ RawObject** from = cls->from();
+ RawObject** to = cls->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kUnresolvedClassCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawUnresolvedClass* cls = objects_[i];
+ s->AssignRef(cls);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawUnresolvedClass* cls = objects_[i];
+ RawObject** from = cls->from();
+ RawObject** to = cls->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ s->WriteTokenPosition(cls->ptr()->token_pos_);
+ }
+ }
+
+ private:
+ GrowableArray<RawUnresolvedClass*> objects_;
+};
+
+
+class UnresolvedClassDeserializationCluster : public DeserializationCluster {
+ public:
+ UnresolvedClassDeserializationCluster() { }
+ virtual ~UnresolvedClassDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ UnresolvedClass::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawUnresolvedClass* cls =
+ reinterpret_cast<RawUnresolvedClass*>(d->Ref(id));
+ Deserializer::InitializeHeader(cls, kUnresolvedClassCid,
+ UnresolvedClass::InstanceSize(),
+ is_vm_object);
+ RawObject** from = cls->from();
+ RawObject** to = cls->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ cls->ptr()->token_pos_ = d->ReadTokenPosition();
+ }
+ }
+};
+
+
+class TypeArgumentsSerializationCluster : public SerializationCluster {
+ public:
+ TypeArgumentsSerializationCluster() { }
+ virtual ~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->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawTypeArguments* type_args = objects_[i];
+ intptr_t length = Smi::Value(type_args->ptr()->length_);
+ s->Write<intptr_t>(length);
+ s->AssignRef(type_args);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawTypeArguments* type_args = objects_[i];
+ intptr_t length = Smi::Value(type_args->ptr()->length_);
+ s->Write<intptr_t>(length);
+ s->Write<bool>(type_args->IsCanonical());
+ intptr_t hash = Smi::Value(type_args->ptr()->hash_);
+ s->Write<int32_t>(hash);
+ s->WriteRef(type_args->ptr()->instantiations_);
+ for (intptr_t j = 0; j < length; j++) {
+ s->WriteRef(type_args->ptr()->types()[j]);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawTypeArguments*> objects_;
+};
+
+
+class TypeArgumentsDeserializationCluster : public DeserializationCluster {
+ public:
+ TypeArgumentsDeserializationCluster() { }
+ virtual ~TypeArgumentsDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->Read<intptr_t>();
+ d->AssignRef(AllocateUninitialized(old_space,
+ TypeArguments::InstanceSize(length)));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawTypeArguments* type_args =
+ reinterpret_cast<RawTypeArguments*>(d->Ref(id));
+ intptr_t length = d->Read<intptr_t>();
+ bool is_canonical = d->Read<bool>();
+ Deserializer::InitializeHeader(type_args, kTypeArgumentsCid,
+ TypeArguments::InstanceSize(length),
+ is_vm_object, 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());
+ }
+ }
+ }
+};
+
+
+class PatchClassSerializationCluster : public SerializationCluster {
+ public:
+ PatchClassSerializationCluster() { }
+ virtual ~PatchClassSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawPatchClass* cls = PatchClass::RawCast(object);
+ objects_.Add(cls);
+
+ RawObject** from = cls->from();
+ RawObject** to = cls->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kPatchClassCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+ RawObject** from = cls->from();
+ RawObject** to = cls->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawPatchClass*> objects_;
+};
+
+
+class PatchClassDeserializationCluster : public DeserializationCluster {
+ public:
+ PatchClassDeserializationCluster() { }
+ virtual ~PatchClassDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ PatchClass::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawPatchClass* cls = reinterpret_cast<RawPatchClass*>(d->Ref(id));
+ Deserializer::InitializeHeader(cls, kPatchClassCid,
+ PatchClass::InstanceSize(), is_vm_object);
+ RawObject** from = cls->from();
+ RawObject** to = cls->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class FunctionSerializationCluster : public SerializationCluster {
+ public:
+ FunctionSerializationCluster() { }
+ virtual ~FunctionSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawFunction* func = Function::RawCast(object);
+ objects_.Add(func);
+
+ RawObject** from = func->from();
+ RawObject** to = func->to_snapshot();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ if (s->kind() == Snapshot::kAppNoJIT) {
+ s->Push(func->ptr()->code_);
+ } else if (s->kind() == Snapshot::kAppWithJIT) {
+ s->Push(func->ptr()->unoptimized_code_);
+ s->Push(func->ptr()->ic_data_array_);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kFunctionCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+ RawObject** from = func->from();
+ RawObject** to = func->to_snapshot();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ if (kind == Snapshot::kAppNoJIT) {
+ s->WriteRef(func->ptr()->code_);
+ } else if (s->kind() == Snapshot::kAppWithJIT) {
+ s->WriteRef(func->ptr()->unoptimized_code_);
+ s->WriteRef(func->ptr()->ic_data_array_);
+ }
+
+ s->WriteTokenPosition(func->ptr()->token_pos_);
+ s->WriteTokenPosition(func->ptr()->end_token_pos_);
+ s->Write<int16_t>(func->ptr()->num_fixed_parameters_);
+ s->Write<int16_t>(func->ptr()->num_optional_parameters_);
+ s->Write<uint32_t>(func->ptr()->kind_tag_);
+ if (kind == Snapshot::kAppNoJIT) {
+ // Omit fields used to support de/reoptimization.
+ } else {
+ bool is_optimized = Code::IsOptimized(func->ptr()->code_);
+ if (is_optimized) {
+ s->Write<int32_t>(FLAG_optimization_counter_threshold);
+ } else {
+ s->Write<int32_t>(0);
+ }
+ s->Write<int8_t>(func->ptr()->deoptimization_counter_);
+ s->Write<uint16_t>(func->ptr()->optimized_instruction_count_);
+ s->Write<uint16_t>(func->ptr()->optimized_call_site_count_);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawFunction*> objects_;
+};
+
+
+class FunctionDeserializationCluster : public DeserializationCluster {
+ public:
+ FunctionDeserializationCluster() { }
+ virtual ~FunctionDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ 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();
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawFunction* func = reinterpret_cast<RawFunction*>(d->Ref(id));
+ Deserializer::InitializeHeader(func, kFunctionCid,
+ Function::InstanceSize(), is_vm_object);
+ RawObject** from = func->from();
+ RawObject** to_snapshot = func->to_snapshot();
+ RawObject** to = func->to();
+ for (RawObject** p = from; p <= to_snapshot; p++) {
+ *p = d->ReadRef();
+ }
+ for (RawObject** p = to_snapshot + 1; p <= to; p++) {
+ *p = Object::null();
+ }
+ if (kind == Snapshot::kAppNoJIT) {
+ func->ptr()->code_ = reinterpret_cast<RawCode*>(d->ReadRef());
+ } else if (kind == Snapshot::kAppWithJIT) {
+ func->ptr()->unoptimized_code_ =
+ reinterpret_cast<RawCode*>(d->ReadRef());
+ func->ptr()->ic_data_array_ = reinterpret_cast<RawArray*>(d->ReadRef());
+ }
+
+#if defined(DEBUG)
+ func->ptr()->entry_point_ = 0;
+#endif
+
+ func->ptr()->token_pos_ = d->ReadTokenPosition();
+ func->ptr()->end_token_pos_ = d->ReadTokenPosition();
+ func->ptr()->num_fixed_parameters_ = d->Read<int16_t>();
+ func->ptr()->num_optional_parameters_ = d->Read<int16_t>();
+ func->ptr()->kind_tag_ = d->Read<uint32_t>();
+ if (kind == Snapshot::kAppNoJIT) {
+ // Omit fields used to support de/reoptimization.
+ } else {
+ func->ptr()->usage_counter_ = d->Read<int32_t>();
+ func->ptr()->deoptimization_counter_ = d->Read<int8_t>();
+ func->ptr()->optimized_instruction_count_ = d->Read<uint16_t>();
+ func->ptr()->optimized_call_site_count_ = d->Read<uint16_t>();
+ }
+ }
+ }
+
+ void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
+ NOT_IN_PRODUCT(TimelineDurationScope tds(Thread::Current(),
+ Timeline::GetIsolateStream(), "PostLoadFunction"));
+
+ if (kind == Snapshot::kAppNoJIT) {
+ 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;
+ }
+ } else if (kind == Snapshot::kAppWithJIT) {
+ 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.unoptimized_code();
+ if (!code.IsNull()) {
+ func.SetInstructions(code);
+ func.set_was_compiled(true);
+ } else {
+ func.ClearCode();
+ func.set_was_compiled(false);
+ }
+ }
+ } else {
+ Function& func = Function::Handle(zone);
+ for (intptr_t i = start_index_; i < stop_index_; i++) {
+ func ^= refs.At(i);
+ func.ClearICDataArray();
+ func.ClearCode();
+ func.set_was_compiled(false);
+ }
+ }
+ }
+};
+
+
+class ClosureDataSerializationCluster : public SerializationCluster {
+ public:
+ ClosureDataSerializationCluster() { }
+ virtual ~ClosureDataSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawClosureData* data = ClosureData::RawCast(object);
+ objects_.Add(data);
+
+ RawObject** from = data->from();
+ RawObject** to = data->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kClosureDataCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+ RawObject** from = data->from();
+ RawObject** to = data->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawClosureData*> objects_;
+};
+
+
+class ClosureDataDeserializationCluster : public DeserializationCluster {
+ public:
+ ClosureDataDeserializationCluster() { }
+ virtual ~ClosureDataDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ ClosureData::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawClosureData* data = reinterpret_cast<RawClosureData*>(d->Ref(id));
+ Deserializer::InitializeHeader(data, kClosureDataCid,
+ ClosureData::InstanceSize(), is_vm_object);
+ RawObject** from = data->from();
+ RawObject** to = data->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class RedirectionDataSerializationCluster : public SerializationCluster {
+ public:
+ RedirectionDataSerializationCluster() { }
+ virtual ~RedirectionDataSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawRedirectionData* data = RedirectionData::RawCast(object);
+ objects_.Add(data);
+
+ RawObject** from = data->from();
+ RawObject** to = data->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kRedirectionDataCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+ RawObject** from = data->from();
+ RawObject** to = data->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawRedirectionData*> objects_;
+};
+
+
+class RedirectionDataDeserializationCluster : public DeserializationCluster {
+ public:
+ RedirectionDataDeserializationCluster() { }
+ virtual ~RedirectionDataDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ RedirectionData::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawRedirectionData* data =
+ reinterpret_cast<RawRedirectionData*>(d->Ref(id));
+ Deserializer::InitializeHeader(data, kRedirectionDataCid,
+ RedirectionData::InstanceSize(),
+ is_vm_object);
+ RawObject** from = data->from();
+ RawObject** to = data->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class FieldSerializationCluster : public SerializationCluster {
+ public:
+ FieldSerializationCluster() { }
+ virtual ~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::kAppNoJIT) {
+ // 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()->initializer_.saved_value_);
+ }
+ } else {
+ s->Push(field->ptr()->value_.offset_);
+ }
+ // Write out the initializer function or saved initial value.
+ if (kind == Snapshot::kAppNoJIT) {
+ s->Push(field->ptr()->initializer_.precompiled_);
+ } else {
+ s->Push(field->ptr()->initializer_.saved_value_);
+ }
+ if (kind != Snapshot::kAppNoJIT) {
+ // Write out the guarded list length.
+ s->Push(field->ptr()->guarded_list_length_);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kFieldCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+
+ s->WriteRef(field->ptr()->name_);
+ s->WriteRef(field->ptr()->owner_);
+ s->WriteRef(field->ptr()->type_);
+ // Write out the initial static value or field offset.
+ if (Field::StaticBit::decode(field->ptr()->kind_bits_)) {
+ if (kind == Snapshot::kAppNoJIT) {
+ // For precompiled static fields, the value was already reset and
+ // initializer_ now contains a Function.
+ s->WriteRef(field->ptr()->value_.static_value_);
+ } else if (Field::ConstBit::decode(field->ptr()->kind_bits_)) {
+ // Do not reset const fields.
+ s->WriteRef(field->ptr()->value_.static_value_);
+ } else {
+ // Otherwise, for static fields we write out the initial static value.
+ s->WriteRef(field->ptr()->initializer_.saved_value_);
+ }
+ } else {
+ s->WriteRef(field->ptr()->value_.offset_);
+ }
+ // Write out the initializer function or saved initial value.
+ if (kind == Snapshot::kAppNoJIT) {
+ s->WriteRef(field->ptr()->initializer_.precompiled_);
+ } else {
+ s->WriteRef(field->ptr()->initializer_.saved_value_);
+ }
+ if (kind != Snapshot::kAppNoJIT) {
+ // Write out the guarded list length.
+ s->WriteRef(field->ptr()->guarded_list_length_);
+ }
+
+ if (kind != Snapshot::kAppNoJIT) {
+ s->WriteTokenPosition(field->ptr()->token_pos_);
+ s->WriteCid(field->ptr()->guarded_cid_);
+ s->WriteCid(field->ptr()->is_nullable_);
+ }
+ s->Write<uint8_t>(field->ptr()->kind_bits_);
+ }
+ }
+
+ private:
+ GrowableArray<RawField*> objects_;
+};
+
+
+class FieldDeserializationCluster : public DeserializationCluster {
+ public:
+ FieldDeserializationCluster() { }
+ virtual ~FieldDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ 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();
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawField* field = reinterpret_cast<RawField*>(d->Ref(id));
+ Deserializer::InitializeHeader(field, kFieldCid,
+ Field::InstanceSize(), is_vm_object);
+ RawObject** from = field->from();
+ RawObject** to_snapshot = field->to_snapshot(kind);
+ RawObject** to = field->to();
+ for (RawObject** p = from; p <= to_snapshot; p++) {
+ *p = d->ReadRef();
+ }
+ for (RawObject** p = to_snapshot + 1; p <= to; p++) {
+ *p = Object::null();
+ }
+
+ if (kind != Snapshot::kAppNoJIT) {
+ field->ptr()->token_pos_ = d->ReadTokenPosition();
+ field->ptr()->guarded_cid_ = d->ReadCid();
+ field->ptr()->is_nullable_ = d->ReadCid();
+ }
+ field->ptr()->kind_bits_ = d->Read<uint8_t>();
+ }
+ }
+
+ void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
+ NOT_IN_PRODUCT(TimelineDurationScope tds(Thread::Current(),
+ Timeline::GetIsolateStream(), "PostLoadField"));
+
+ Field& field = Field::Handle(zone);
+ if (!FLAG_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);
+ }
+ } else {
+ for (intptr_t i = start_index_; i < stop_index_; i++) {
+ field ^= refs.At(i);
+ field.InitializeGuardedListLengthInObjectOffset();
+ }
+ }
+ }
+};
+
+
+class LiteralTokenSerializationCluster : public SerializationCluster {
+ public:
+ LiteralTokenSerializationCluster() { }
+ virtual ~LiteralTokenSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawLiteralToken* token = LiteralToken::RawCast(object);
+ objects_.Add(token);
+
+ RawObject** from = token->from();
+ RawObject** to = token->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kLiteralTokenCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawLiteralToken* token = objects_[i];
+ s->AssignRef(token);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawLiteralToken* token = objects_[i];
+ RawObject** from = token->from();
+ RawObject** to = token->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ s->Write<int32_t>(token->ptr()->kind_);
+ }
+ }
+
+ private:
+ GrowableArray<RawLiteralToken*> objects_;
+};
+
+
+class LiteralTokenDeserializationCluster : public DeserializationCluster {
+ public:
+ LiteralTokenDeserializationCluster() { }
+ virtual ~LiteralTokenDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ LiteralToken::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawLiteralToken* token = reinterpret_cast<RawLiteralToken*>(d->Ref(id));
+ Deserializer::InitializeHeader(token, kLiteralTokenCid,
+ LiteralToken::InstanceSize(),
+ is_vm_object);
+ RawObject** from = token->from();
+ RawObject** to = token->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ token->ptr()->kind_ = static_cast<Token::Kind>(d->Read<int32_t>());
+ }
+ }
+};
+
+
+class TokenStreamSerializationCluster : public SerializationCluster {
+ public:
+ TokenStreamSerializationCluster() { }
+ virtual ~TokenStreamSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawTokenStream* stream = TokenStream::RawCast(object);
+ objects_.Add(stream);
+
+ RawObject** from = stream->from();
+ RawObject** to = stream->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kTokenStreamCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawTokenStream* stream = objects_[i];
+ s->AssignRef(stream);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawTokenStream* stream = objects_[i];
+ RawObject** from = stream->from();
+ RawObject** to = stream->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawTokenStream*> objects_;
+};
+
+
+class TokenStreamDeserializationCluster : public DeserializationCluster {
+ public:
+ TokenStreamDeserializationCluster() { }
+ virtual ~TokenStreamDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ TokenStream::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawTokenStream* stream = reinterpret_cast<RawTokenStream*>(d->Ref(id));
+ Deserializer::InitializeHeader(stream, kTokenStreamCid,
+ TokenStream::InstanceSize(), is_vm_object);
+ RawObject** from = stream->from();
+ RawObject** to = stream->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class ScriptSerializationCluster : public SerializationCluster {
+ public:
+ ScriptSerializationCluster() { }
+ virtual ~ScriptSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawScript* script = Script::RawCast(object);
+ objects_.Add(script);
+
+ RawObject** from = script->from();
+ RawObject** to = script->to_snapshot(s->kind());
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kScriptCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawScript* script = objects_[i];
+ s->AssignRef(script);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ Snapshot::Kind kind = s->kind();
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawScript* script = objects_[i];
+ RawObject** from = script->from();
+ RawObject** to = script->to_snapshot(kind);
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+
+ s->Write<int32_t>(script->ptr()->line_offset_);
+ s->Write<int32_t>(script->ptr()->col_offset_);
+ s->Write<int8_t>(script->ptr()->kind_);
+ }
+ }
+
+ private:
+ GrowableArray<RawScript*> objects_;
+};
+
+
+class ScriptDeserializationCluster : public DeserializationCluster {
+ public:
+ ScriptDeserializationCluster() { }
+ virtual ~ScriptDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, Script::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ Snapshot::Kind kind = d->kind();
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawScript* script = reinterpret_cast<RawScript*>(d->Ref(id));
+ Deserializer::InitializeHeader(script, kScriptCid,
+ Script::InstanceSize(), is_vm_object);
+ RawObject** from = script->from();
+ RawObject** to_snapshot = script->to_snapshot(kind);
+ RawObject** to = script->to();
+ for (RawObject** p = from; p <= to_snapshot; p++) {
+ *p = d->ReadRef();
+ }
+ for (RawObject** p = to_snapshot + 1; p <= to; p++) {
+ *p = Object::null();
+ }
+
+ 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()->load_timestamp_ = 0;
+ }
+ }
+};
+
+
+class LibrarySerializationCluster : public SerializationCluster {
+ public:
+ LibrarySerializationCluster() { }
+ virtual ~LibrarySerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawLibrary* lib = Library::RawCast(object);
+ objects_.Add(lib);
+
+ RawObject** from = lib->from();
+ RawObject** to = lib->to_snapshot();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kLibraryCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+ RawObject** from = lib->from();
+ RawObject** to = lib->to_snapshot();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+
+ 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()->corelib_imported_);
+ s->Write<bool>(lib->ptr()->is_dart_scheme_);
+ s->Write<bool>(lib->ptr()->debuggable_);
+ }
+ }
+
+ private:
+ GrowableArray<RawLibrary*> objects_;
+};
+
+class LibraryDeserializationCluster : public DeserializationCluster {
+ public:
+ LibraryDeserializationCluster() { }
+ virtual ~LibraryDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, Library::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawLibrary* lib = reinterpret_cast<RawLibrary*>(d->Ref(id));
+ Deserializer::InitializeHeader(lib, kLibraryCid,
+ Library::InstanceSize(), is_vm_object);
+ RawObject** from = lib->from();
+ RawObject** to_snapshot = lib->to_snapshot();
+ RawObject** to = lib->to();
+ for (RawObject** p = from; p <= to_snapshot; p++) {
+ *p = d->ReadRef();
+ }
+ for (RawObject** p = to_snapshot + 1; p <= to; p++) {
+ *p = Object::null();
+ }
+
+ 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()->corelib_imported_ = d->Read<bool>();
+ lib->ptr()->is_dart_scheme_ = d->Read<bool>();
+ lib->ptr()->debuggable_ = d->Read<bool>();
+ lib->ptr()->is_in_fullsnapshot_ = true;
+ }
+ }
+
+ void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
+ // TODO(rmacnak): This is surprisingly slow, roughly 20% of deserialization
+ // time for the JIT. Maybe make the lookups happy with a null?
+
+ NOT_IN_PRODUCT(TimelineDurationScope tds(Thread::Current(),
+ Timeline::GetIsolateStream(), "PostLoadLibrary"));
+
+ Library& lib = Library::Handle(zone);
+ for (intptr_t i = start_index_; i < stop_index_; i++) {
+ lib ^= refs.At(i);
+ const intptr_t kInitialNameCacheSize = 64;
+ lib.InitResolvedNamesCache(kInitialNameCacheSize);
+ }
+ }
+};
+
+
+class NamespaceSerializationCluster : public SerializationCluster {
+ public:
+ NamespaceSerializationCluster() { }
+ virtual ~NamespaceSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawNamespace* ns = Namespace::RawCast(object);
+ objects_.Add(ns);
+
+ RawObject** from = ns->from();
+ RawObject** to = ns->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kNamespaceCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+ RawObject** from = ns->from();
+ RawObject** to = ns->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawNamespace*> objects_;
+};
+
+
+class NamespaceDeserializationCluster : public DeserializationCluster {
+ public:
+ NamespaceDeserializationCluster() { }
+ virtual ~NamespaceDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, Namespace::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawNamespace* ns = reinterpret_cast<RawNamespace*>(d->Ref(id));
+ Deserializer::InitializeHeader(ns, kNamespaceCid,
+ Namespace::InstanceSize(), is_vm_object);
+ RawObject** from = ns->from();
+ RawObject** to = ns->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class CodeSerializationCluster : public SerializationCluster {
+ public:
+ CodeSerializationCluster() { }
+ virtual ~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_);
+ s->Push(code->ptr()->stackmaps_);
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kCodeCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+
+ 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::kAppNoJIT) {
+ // No disabled code in precompilation.
+ ASSERT(code->ptr()->instructions_ == code->ptr()->active_instructions_);
+ } else {
+ ASSERT(kind == Snapshot::kAppWithJIT);
+ // We never include optimized code in JIT precompilation. Deoptimization
+ // requires code patching and we cannot patch code that is shared
+ // between isolates and should not mutate memory allocated by the
+ // embedder.
+ bool is_optimized = Code::PtrOffBits::decode(code->ptr()->state_bits_);
+ if (is_optimized) {
+ FATAL("Cannot include optimized code in a JIT snapshot");
+ }
+ }
+
+ RawInstructions* instr = code->ptr()->instructions_;
+ int32_t text_offset = s->GetTextOffset(instr, code);
+ s->Write<int32_t>(text_offset);
+
+ s->WriteRef(code->ptr()->object_pool_);
+ s->WriteRef(code->ptr()->owner_);
+ s->WriteRef(code->ptr()->exception_handlers_);
+ s->WriteRef(code->ptr()->pc_descriptors_);
+ s->WriteRef(code->ptr()->stackmaps_);
+
+ s->Write<int32_t>(code->ptr()->state_bits_);
+ }
+ }
+
+ private:
+ GrowableArray<RawCode*> objects_;
+};
+
+
+class CodeDeserializationCluster : public DeserializationCluster {
+ public:
+ CodeDeserializationCluster() { }
+ virtual ~CodeDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, Code::InstanceSize(0)));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ 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), is_vm_object);
+
+ int32_t text_offset = d->Read<int32_t>();
+ RawInstructions* instr = reinterpret_cast<RawInstructions*>(
+ d->GetInstructionsAt(text_offset) + kHeapObjectTag);
+ uword entry_point = Instructions::EntryPoint(instr);
+
+ code->ptr()->entry_point_ = entry_point;
+ code->ptr()->active_instructions_ = instr;
+ code->ptr()->instructions_ = instr;
+ 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());
+ code->ptr()->stackmaps_ =
+ reinterpret_cast<RawArray*>(d->ReadRef());
+
+ code->ptr()->deopt_info_array_ = Array::null();
+ code->ptr()->static_calls_target_table_ = Array::null();
+ code->ptr()->var_descriptors_ = LocalVarDescriptors::null();
+ code->ptr()->inlined_metadata_ = Array::null();
+ code->ptr()->code_source_map_ = CodeSourceMap::null();
+ code->ptr()->comments_ = Array::null();
+ code->ptr()->return_address_metadata_ = Object::null();
+
+ code->ptr()->compile_timestamp_ = 0;
+ code->ptr()->state_bits_ = d->Read<int32_t>();
+ code->ptr()->lazy_deopt_pc_offset_ = -1;
+ }
+ }
+};
+
+
+class ObjectPoolSerializationCluster : public SerializationCluster {
+ public:
+ ObjectPoolSerializationCluster() { }
+ virtual ~ObjectPoolSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawObjectPool* pool = ObjectPool::RawCast(object);
+ objects_.Add(pool);
+
+ intptr_t length = pool->ptr()->length_;
+ RawTypedData* info_array = pool->ptr()->info_array_;
+
+ for (intptr_t i = 0; i < length; i++) {
+ ObjectPool::EntryType entry_type =
+ static_cast<ObjectPool::EntryType>(info_array->ptr()->data()[i]);
+ if (entry_type == ObjectPool::kTaggedObject) {
+ s->Push(pool->ptr()->data()[i].raw_obj_);
+ }
+ }
+
+ // TODO(rmacnak): Allocate the object pool and its info array together.
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kObjectPoolCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawObjectPool* pool = objects_[i];
+ intptr_t length = pool->ptr()->length_;
+ s->Write<intptr_t>(length);
+ s->AssignRef(pool);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawObjectPool* pool = objects_[i];
+ RawTypedData* info_array = pool->ptr()->info_array_;
+ intptr_t length = pool->ptr()->length_;
+ s->Write<intptr_t>(length);
+ for (intptr_t j = 0; j < length; j++) {
+ ObjectPool::EntryType entry_type =
+ static_cast<ObjectPool::EntryType>(info_array->ptr()->data()[j]);
+ s->Write<int8_t>(entry_type);
+ RawObjectPool::Entry& entry = pool->ptr()->data()[j];
+ switch (entry_type) {
+ case ObjectPool::kTaggedObject: {
+#if !defined(TARGET_ARCH_DBC)
+ if (entry.raw_obj_ ==
+ StubCode::CallNativeCFunction_entry()->code()) {
+ // Natives can run while precompiling, becoming linked and
+ // switching their stub. Reset to the initial stub used for
+ // lazy-linking.
+ s->WriteRef(StubCode::CallBootstrapCFunction_entry()->code());
+ break;
+ }
+#endif
+ s->WriteRef(entry.raw_obj_);
+ break;
+ }
+ case ObjectPool::kImmediate: {
+ s->Write<intptr_t>(entry.raw_value_);
+ break;
+ }
+ case ObjectPool::kNativeEntry: {
+ // Write nothing. Will initialize with the lazy link entry.
+#if defined(TARGET_ARCH_DBC)
+ UNREACHABLE(); // DBC does not support lazy native call linking.
+#endif
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawObjectPool*> objects_;
+};
+
+
+class ObjectPoolDeserializationCluster : public DeserializationCluster {
+ public:
+ ObjectPoolDeserializationCluster() { }
+ virtual ~ObjectPoolDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->Read<intptr_t>();
+ d->AssignRef(AllocateUninitialized(old_space,
+ ObjectPool::InstanceSize(length)));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+ PageSpace* old_space = d->heap()->old_space();
+ for (intptr_t id = start_index_; id < stop_index_; id += 1) {
+ intptr_t length = d->Read<intptr_t>();
+ RawTypedData* info_array = reinterpret_cast<RawTypedData*>(
+ AllocateUninitialized(old_space, TypedData::InstanceSize(length)));
+ Deserializer::InitializeHeader(info_array, kTypedDataUint8ArrayCid,
+ TypedData::InstanceSize(length),
+ is_vm_object);
+ info_array->ptr()->length_ = Smi::New(length);
+ RawObjectPool* pool = reinterpret_cast<RawObjectPool*>(d->Ref(id + 0));
+ Deserializer::InitializeHeader(pool, kObjectPoolCid,
+ ObjectPool::InstanceSize(length),
+ is_vm_object);
+ pool->ptr()->length_ = length;
+ pool->ptr()->info_array_ = info_array;
+ for (intptr_t j = 0; j < length; j++) {
+ ObjectPool::EntryType entry_type =
+ static_cast<ObjectPool::EntryType>(d->Read<int8_t>());
+ info_array->ptr()->data()[j] = entry_type;
+ RawObjectPool::Entry& entry = pool->ptr()->data()[j];
+ switch (entry_type) {
+ case ObjectPool::kTaggedObject:
+ entry.raw_obj_ = d->ReadRef();
+ break;
+ case ObjectPool::kImmediate:
+ entry.raw_value_ = d->Read<intptr_t>();
+ break;
+ case ObjectPool::kNativeEntry: {
+#if !defined(TARGET_ARCH_DBC)
+ // Read nothing. Initialize with the lazy link entry.
+ uword new_entry = NativeEntry::LinkNativeCallEntry();
+ entry.raw_value_ = static_cast<intptr_t>(new_entry);
+#else
+ UNREACHABLE(); // DBC does not support lazy native call linking.
+#endif
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+ }
+};
+
+
+// PcDescriptor, Stackmap, OneByteString, TwoByteString
+class RODataSerializationCluster : public SerializationCluster {
+ public:
+ explicit RODataSerializationCluster(intptr_t cid) : cid_(cid) { }
+ virtual ~RODataSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ objects_.Add(object);
+
+ // A string's hash must already be computed when we write it because it
+ // will be loaded into read-only memory.
+ if (cid_ == kOneByteStringCid) {
+ RawOneByteString* str = static_cast<RawOneByteString*>(object);
+ if (str->ptr()->hash_ == Smi::New(0)) {
+ intptr_t hash = String::Hash(str->ptr()->data(),
+ Smi::Value(str->ptr()->length_));
+ str->ptr()->hash_ = Smi::New(hash);
+ }
+ ASSERT(str->ptr()->hash_ != Smi::New(0));
+ } else if (cid_ == kTwoByteStringCid) {
+ RawTwoByteString* str = static_cast<RawTwoByteString*>(object);
+ if (str->ptr()->hash_ == Smi::New(0)) {
+ intptr_t hash = String::Hash(str->ptr()->data(),
+ Smi::Value(str->ptr()->length_) * 2);
+ str->ptr()->hash_ = Smi::New(hash);
+ }
+ ASSERT(str->ptr()->hash_ != Smi::New(0));
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(cid_);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawObject* object = objects_[i];
+ int32_t rodata_offset = s->GetRODataOffset(object);
+ s->Write<int32_t>(rodata_offset);
+ s->AssignRef(object);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ // No-op.
+ }
+
+ private:
+ const intptr_t cid_;
+ GrowableArray<RawObject*> objects_;
+};
+
+
+class RODataDeserializationCluster : public DeserializationCluster {
+ public:
+ RODataDeserializationCluster() { }
+ virtual ~RODataDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ int32_t rodata_offset = d->Read<int32_t>();
+ d->AssignRef(d->GetObjectAt(rodata_offset));
+ }
+ }
+
+ void ReadFill(Deserializer* d) {
+ // No-op.
+ }
+};
+
+
+class LocalVarDescriptorsSerializationCluster : public SerializationCluster {
+ public:
+ LocalVarDescriptorsSerializationCluster() { }
+ virtual ~LocalVarDescriptorsSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) { UNIMPLEMENTED(); }
+ void WriteAlloc(Serializer* s) {}
+ void WriteFill(Serializer* s) {}
+
+ private:
+ GrowableArray<RawClass*> objects_;
+};
+
+
+class ExceptionHandlersSerializationCluster : public SerializationCluster {
+ public:
+ ExceptionHandlersSerializationCluster() { }
+ virtual ~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->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawExceptionHandlers* handlers = objects_[i];
+ intptr_t length = handlers->ptr()->num_entries_;
+ s->Write<intptr_t>(length);
+ s->AssignRef(handlers);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawExceptionHandlers* handlers = objects_[i];
+ intptr_t length = handlers->ptr()->num_entries_;
+ s->Write<intptr_t>(length);
+ s->WriteRef(handlers->ptr()->handled_types_data_);
+
+ uint8_t* data = reinterpret_cast<uint8_t*>(handlers->ptr()->data());
+ intptr_t length_in_bytes =
+ length * sizeof(RawExceptionHandlers::HandlerInfo);
+ s->WriteBytes(data, length_in_bytes);
+ }
+ }
+
+ private:
+ GrowableArray<RawExceptionHandlers*> objects_;
+};
+
+
+class ExceptionHandlersDeserializationCluster : public DeserializationCluster {
+ public:
+ ExceptionHandlersDeserializationCluster() { }
+ virtual ~ExceptionHandlersDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->Read<intptr_t>();
+ d->AssignRef(AllocateUninitialized(old_space,
+ ExceptionHandlers::InstanceSize(length)));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawExceptionHandlers* handlers =
+ reinterpret_cast<RawExceptionHandlers*>(d->Ref(id));
+ intptr_t length = d->Read<intptr_t>();
+ Deserializer::InitializeHeader(handlers, kExceptionHandlersCid,
+ ExceptionHandlers::InstanceSize(length),
+ is_vm_object);
+ handlers->ptr()->num_entries_ = length;
+ handlers->ptr()->handled_types_data_ =
+ reinterpret_cast<RawArray*>(d->ReadRef());
+
+ uint8_t* data = reinterpret_cast<uint8_t*>(handlers->ptr()->data());
+ intptr_t length_in_bytes =
+ length * sizeof(RawExceptionHandlers::HandlerInfo);
+ d->ReadBytes(data, length_in_bytes);
+ }
+ }
+};
+
+class ContextSerializationCluster : public SerializationCluster {
+ public:
+ ContextSerializationCluster() { }
+ virtual ~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->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawContext* context = objects_[i];
+ intptr_t length = context->ptr()->num_variables_;
+ s->Write<intptr_t>(length);
+ s->AssignRef(context);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawContext* context = objects_[i];
+ intptr_t length = context->ptr()->num_variables_;
+ s->Write<intptr_t>(length);
+ s->WriteRef(context->ptr()->parent_);
+ for (intptr_t j = 0; j < length; j++) {
+ s->WriteRef(context->ptr()->data()[j]);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawContext*> objects_;
+};
+
+
+class ContextDeserializationCluster : public DeserializationCluster {
+ public:
+ ContextDeserializationCluster() { }
+ virtual ~ContextDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->Read<intptr_t>();
+ d->AssignRef(AllocateUninitialized(old_space,
+ Context::InstanceSize(length)));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawContext* context = reinterpret_cast<RawContext*>(d->Ref(id));
+ intptr_t length = d->Read<intptr_t>();
+ Deserializer::InitializeHeader(context, kContextCid,
+ Context::InstanceSize(length),
+ is_vm_object);
+ 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();
+ }
+ }
+ }
+};
+
+
+class ContextScopeSerializationCluster : public SerializationCluster {
+ public:
+ ContextScopeSerializationCluster() { }
+ virtual ~ContextScopeSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawContextScope* scope = ContextScope::RawCast(object);
+ objects_.Add(scope);
+
+ intptr_t length = scope->ptr()->num_variables_;
+ RawObject** from = scope->from();
+ RawObject** to = scope->to(length);
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kContextScopeCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawContextScope* scope = objects_[i];
+ intptr_t length = scope->ptr()->num_variables_;
+ s->Write<intptr_t>(length);
+ s->AssignRef(scope);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawContextScope* scope = objects_[i];
+ intptr_t length = scope->ptr()->num_variables_;
+ s->Write<intptr_t>(length);
+ s->Write<bool>(scope->ptr()->is_implicit_);
+ RawObject** from = scope->from();
+ RawObject** to = scope->to(length);
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawContextScope*> objects_;
+};
+
+
+class ContextScopeDeserializationCluster : public DeserializationCluster {
+ public:
+ ContextScopeDeserializationCluster() { }
+ virtual ~ContextScopeDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->Read<intptr_t>();
+ d->AssignRef(AllocateUninitialized(old_space,
+ ContextScope::InstanceSize(length)));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawContextScope* scope = reinterpret_cast<RawContextScope*>(d->Ref(id));
+ intptr_t length = d->Read<intptr_t>();
+ Deserializer::InitializeHeader(scope, kContextScopeCid,
+ ContextScope::InstanceSize(length),
+ is_vm_object);
+ scope->ptr()->num_variables_ = length;
+ scope->ptr()->is_implicit_ = d->Read<bool>();
+ RawObject** from = scope->from();
+ RawObject** to = scope->to(length);
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class ICDataSerializationCluster : public SerializationCluster {
+ public:
+ ICDataSerializationCluster() { }
+ virtual ~ICDataSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawICData* ic = ICData::RawCast(object);
+ objects_.Add(ic);
+
+ RawObject** from = ic->from();
+ RawObject** to = ic->to_snapshot(s->kind());
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kICDataCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+ RawObject** from = ic->from();
+ RawObject** to = ic->to_snapshot(kind);
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ s->Write<int32_t>(ic->ptr()->deopt_id_);
+ s->Write<uint32_t>(ic->ptr()->state_bits_);
+#if defined(TAG_IC_DATA)
+ s->Write<intptr_t>(ic->ptr()->tag_);
+#endif
+ }
+ }
+
+ private:
+ GrowableArray<RawICData*> objects_;
+};
+
+
+class ICDataDeserializationCluster : public DeserializationCluster {
+ public:
+ ICDataDeserializationCluster() { }
+ virtual ~ICDataDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, ICData::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ Snapshot::Kind kind = d->kind();
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawICData* ic = reinterpret_cast<RawICData*>(d->Ref(id));
+ Deserializer::InitializeHeader(ic, kICDataCid,
+ ICData::InstanceSize(), is_vm_object);
+ RawObject** from = ic->from();
+ RawObject** to_snapshot = ic->to_snapshot(kind);
+ RawObject** to = ic->to();
+ for (RawObject** p = from; p <= to_snapshot; p++) {
+ *p = d->ReadRef();
+ }
+ for (RawObject** p = to_snapshot + 1; p <= to; p++) {
+ *p = Object::null();
+ }
+ ic->ptr()->deopt_id_ = d->Read<int32_t>();
+ ic->ptr()->state_bits_ = d->Read<int32_t>();
+#if defined(TAG_IC_DATA)
+ ic->ptr()->tag_ = d->Read<intptr_t>();
+#endif
+ }
+ }
+
+ void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
+ NOT_IN_PRODUCT(TimelineDurationScope tds(Thread::Current(),
+ Timeline::GetIsolateStream(), "PostLoadICData"));
+
+ if (kind == Snapshot::kAppNoJIT) {
+ ICData& ic = ICData::Handle(zone);
+ Object& funcOrCode = Object::Handle(zone);
+ Code& code = Code::Handle(zone);
+ Smi& entry_point = Smi::Handle(zone);
+ for (intptr_t i = start_index_; i < stop_index_; i++) {
+ ic ^= refs.At(i);
+ for (intptr_t j = 0; j < ic.NumberOfChecks(); j++) {
+ funcOrCode = ic.GetTargetOrCodeAt(j);
+ if (funcOrCode.IsCode()) {
+ code ^= funcOrCode.raw();
+ entry_point = Smi::FromAlignedAddress(code.EntryPoint());
+ ic.SetEntryPointAt(j, entry_point);
+ }
+ }
+ }
+ }
+ }
+};
+
+
+class MegamorphicCacheSerializationCluster : public SerializationCluster {
+ public:
+ MegamorphicCacheSerializationCluster() { }
+ virtual ~MegamorphicCacheSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawMegamorphicCache* cache = MegamorphicCache::RawCast(object);
+ objects_.Add(cache);
+
+ RawObject** from = cache->from();
+ RawObject** to = cache->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kMegamorphicCacheCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+ RawObject** from = cache->from();
+ RawObject** to = cache->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ s->Write<int32_t>(cache->ptr()->filled_entry_count_);
+ }
+ }
+
+ private:
+ GrowableArray<RawMegamorphicCache*> objects_;
+};
+
+
+class MegamorphicCacheDeserializationCluster : public DeserializationCluster {
+ public:
+ MegamorphicCacheDeserializationCluster() { }
+ virtual ~MegamorphicCacheDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ MegamorphicCache::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawMegamorphicCache* cache =
+ reinterpret_cast<RawMegamorphicCache*>(d->Ref(id));
+ Deserializer::InitializeHeader(cache, kMegamorphicCacheCid,
+ MegamorphicCache::InstanceSize(),
+ is_vm_object);
+ RawObject** from = cache->from();
+ RawObject** to = cache->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ cache->ptr()->filled_entry_count_ = d->Read<int32_t>();
+ }
+ }
+};
+
+
+class SubtypeTestCacheSerializationCluster : public SerializationCluster {
+ public:
+ SubtypeTestCacheSerializationCluster() { }
+ virtual ~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->Write<intptr_t>(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];
+ s->WriteRef(cache->ptr()->cache_);
+ }
+ }
+
+ private:
+ GrowableArray<RawSubtypeTestCache*> objects_;
+};
+
+
+class SubtypeTestCacheDeserializationCluster : public DeserializationCluster {
+ public:
+ SubtypeTestCacheDeserializationCluster() { }
+ virtual ~SubtypeTestCacheDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ SubtypeTestCache::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawSubtypeTestCache* cache =
+ reinterpret_cast<RawSubtypeTestCache*>(d->Ref(id));
+ Deserializer::InitializeHeader(cache, kSubtypeTestCacheCid,
+ SubtypeTestCache::InstanceSize(),
+ is_vm_object);
+ cache->ptr()->cache_ = reinterpret_cast<RawArray*>(d->ReadRef());
+ }
+ }
+};
+
+
+class LanguageErrorSerializationCluster : public SerializationCluster {
+ public:
+ LanguageErrorSerializationCluster() { }
+ virtual ~LanguageErrorSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawLanguageError* error = LanguageError::RawCast(object);
+ objects_.Add(error);
+
+ RawObject** from = error->from();
+ RawObject** to = error->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kLanguageErrorCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+ RawObject** from = error->from();
+ RawObject** to = error->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ 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_;
+};
+
+
+class LanguageErrorDeserializationCluster : public DeserializationCluster {
+ public:
+ LanguageErrorDeserializationCluster() { }
+ virtual ~LanguageErrorDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ LanguageError::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawLanguageError* error = reinterpret_cast<RawLanguageError*>(d->Ref(id));
+ Deserializer::InitializeHeader(error, kLanguageErrorCid,
+ LanguageError::InstanceSize(),
+ is_vm_object);
+ RawObject** from = error->from();
+ RawObject** to = error->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ error->ptr()->token_pos_ = d->ReadTokenPosition();
+ error->ptr()->report_after_token_ = d->Read<bool>();
+ error->ptr()->kind_ = d->Read<int8_t>();
+ }
+ }
+};
+
+
+class UnhandledExceptionSerializationCluster : public SerializationCluster {
+ public:
+ UnhandledExceptionSerializationCluster() { }
+ virtual ~UnhandledExceptionSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawUnhandledException* exception = UnhandledException::RawCast(object);
+ objects_.Add(exception);
+
+ RawObject** from = exception->from();
+ RawObject** to = exception->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kUnhandledExceptionCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+ RawObject** from = exception->from();
+ RawObject** to = exception->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawUnhandledException*> objects_;
+};
+
+
+class UnhandledExceptionDeserializationCluster : public DeserializationCluster {
+ public:
+ UnhandledExceptionDeserializationCluster() { }
+ virtual ~UnhandledExceptionDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ UnhandledException::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawUnhandledException* exception =
+ reinterpret_cast<RawUnhandledException*>(d->Ref(id));
+ Deserializer::InitializeHeader(exception, kUnhandledExceptionCid,
+ UnhandledException::InstanceSize(),
+ is_vm_object);
+ RawObject** from = exception->from();
+ RawObject** to = exception->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class InstanceSerializationCluster : public SerializationCluster {
+ public:
+ explicit InstanceSerializationCluster(intptr_t cid) : cid_(cid) {
+ RawClass* cls = Isolate::Current()->class_table()->At(cid);
+ next_field_offset_ =
+ cls->ptr()->next_field_offset_in_words_ << kWordSizeLog2;
+ instance_size_in_words_ = cls->ptr()->instance_size_in_words_;
+ ASSERT(next_field_offset_ > 0);
+ ASSERT(instance_size_in_words_ > 0);
+ }
+ virtual ~InstanceSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawInstance* instance = Instance::RawCast(object);
+ objects_.Add(instance);
+
+ 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->Write<intptr_t>(cid_);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+
+ s->Write<intptr_t>(next_field_offset_);
+ s->Write<intptr_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 count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawInstance* instance = objects_[i];
+ 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->WriteRef(raw_obj);
+ offset += kWordSize;
+ }
+ }
+ }
+
+ private:
+ const intptr_t cid_;
+ intptr_t next_field_offset_;
+ intptr_t instance_size_in_words_;
+ GrowableArray<RawInstance*> objects_;
+};
+
+
+class InstanceDeserializationCluster : public DeserializationCluster {
+ public:
+ explicit InstanceDeserializationCluster(intptr_t cid) : cid_(cid) { }
+ virtual ~InstanceDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ next_field_offset_ = d->Read<intptr_t>();
+ instance_size_in_words_ = d->Read<intptr_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 instance_size =
+ Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize);
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ 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_vm_object, 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_;
+ intptr_t instance_size_in_words_;
+};
+
+
+class LibraryPrefixSerializationCluster : public SerializationCluster {
+ public:
+ LibraryPrefixSerializationCluster() { }
+ virtual ~LibraryPrefixSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawLibraryPrefix* prefix = LibraryPrefix::RawCast(object);
+ objects_.Add(prefix);
+
+ RawObject** from = prefix->from();
+ RawObject** to = prefix->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kLibraryPrefixCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(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];
+ RawObject** from = prefix->from();
+ RawObject** to = prefix->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ s->Write<uint16_t>(prefix->ptr()->num_imports_);
+ s->Write<bool>(prefix->ptr()->is_deferred_load_);
+ s->Write<bool>(prefix->ptr()->is_loaded_);
+ }
+ }
+
+ private:
+ GrowableArray<RawLibraryPrefix*> objects_;
+};
+
+
+class LibraryPrefixDeserializationCluster : public DeserializationCluster {
+ public:
+ LibraryPrefixDeserializationCluster() { }
+ virtual ~LibraryPrefixDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ LibraryPrefix::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawLibraryPrefix* prefix =
+ reinterpret_cast<RawLibraryPrefix*>(d->Ref(id));
+ Deserializer::InitializeHeader(prefix, kLibraryPrefixCid,
+ LibraryPrefix::InstanceSize(),
+ is_vm_object);
+ RawObject** from = prefix->from();
+ RawObject** to = prefix->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ prefix->ptr()->num_imports_ = d->Read<uint16_t>();
+ prefix->ptr()->is_deferred_load_ = d->Read<bool>();
+ prefix->ptr()->is_loaded_ = d->Read<bool>();
+ }
+ }
+};
+
+
+class TypeSerializationCluster : public SerializationCluster {
+ public:
+ TypeSerializationCluster() { }
+ virtual ~TypeSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawType* type = Type::RawCast(object);
+ if (type->IsCanonical()) {
+ canonical_objects_.Add(type);
+ } else {
+ objects_.Add(type);
+ }
+
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+
+ RawSmi* raw_type_class_id = Smi::RawCast(type->ptr()->type_class_id_);
+ RawClass* type_class =
+ s->isolate()->class_table()->At(Smi::Value(raw_type_class_id));
+ s->Push(type_class);
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kTypeCid);
+ intptr_t count = canonical_objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawType* type = canonical_objects_[i];
+ s->AssignRef(type);
+ }
+ count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawType* type = objects_[i];
+ s->AssignRef(type);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = canonical_objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawType* type = canonical_objects_[i];
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ s->WriteTokenPosition(type->ptr()->token_pos_);
+ s->Write<int8_t>(type->ptr()->type_state_);
+ }
+ count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawType* type = objects_[i];
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ s->WriteTokenPosition(type->ptr()->token_pos_);
+ s->Write<int8_t>(type->ptr()->type_state_);
+ }
+ }
+
+ private:
+ GrowableArray<RawType*> canonical_objects_;
+ GrowableArray<RawType*> objects_;
+};
+
+
+class TypeDeserializationCluster : public DeserializationCluster {
+ public:
+ TypeDeserializationCluster() { }
+ virtual ~TypeDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ canonical_start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, Type::InstanceSize()));
+ }
+ canonical_stop_index_ = d->next_index();
+
+ start_index_ = d->next_index();
+ count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, Type::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = canonical_start_index_;
+ id < canonical_stop_index_;
+ id++) {
+ RawType* type = reinterpret_cast<RawType*>(d->Ref(id));
+ Deserializer::InitializeHeader(type, kTypeCid,
+ Type::InstanceSize(), is_vm_object, true);
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ type->ptr()->token_pos_ = d->ReadTokenPosition();
+ type->ptr()->type_state_ = d->Read<int8_t>();
+ }
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawType* type = reinterpret_cast<RawType*>(d->Ref(id));
+ Deserializer::InitializeHeader(type, kTypeCid,
+ Type::InstanceSize(), is_vm_object);
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ type->ptr()->token_pos_ = d->ReadTokenPosition();
+ type->ptr()->type_state_ = d->Read<int8_t>();
+ }
+ }
+
+ private:
+ intptr_t canonical_start_index_;
+ intptr_t canonical_stop_index_;
+};
+
+
+class TypeRefSerializationCluster : public SerializationCluster {
+ public:
+ TypeRefSerializationCluster() { }
+ virtual ~TypeRefSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawTypeRef* type = TypeRef::RawCast(object);
+ objects_.Add(type);
+
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kTypeRefCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawTypeRef* type = objects_[i];
+ s->AssignRef(type);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawTypeRef* type = objects_[i];
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawTypeRef*> objects_;
+};
+
+
+class TypeRefDeserializationCluster : public DeserializationCluster {
+ public:
+ TypeRefDeserializationCluster() { }
+ virtual ~TypeRefDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, TypeRef::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawTypeRef* type = reinterpret_cast<RawTypeRef*>(d->Ref(id));
+ Deserializer::InitializeHeader(type, kTypeRefCid,
+ TypeRef::InstanceSize(), is_vm_object);
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class TypeParameterSerializationCluster : public SerializationCluster {
+ public:
+ TypeParameterSerializationCluster() { }
+ virtual ~TypeParameterSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawTypeParameter* type = TypeParameter::RawCast(object);
+ objects_.Add(type);
+ ASSERT(!type->IsCanonical());
+
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kTypeParameterCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawTypeParameter* type = objects_[i];
+ s->AssignRef(type);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawTypeParameter* type = objects_[i];
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ s->Write<intptr_t>(type->ptr()->parameterized_class_id_);
+ s->WriteTokenPosition(type->ptr()->token_pos_);
+ s->Write<int16_t>(type->ptr()->index_);
+ s->Write<int8_t>(type->ptr()->type_state_);
+ }
+ }
+
+ private:
+ GrowableArray<RawTypeParameter*> objects_;
+};
+
+
+class TypeParameterDeserializationCluster : public DeserializationCluster {
+ public:
+ TypeParameterDeserializationCluster() { }
+ virtual ~TypeParameterDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ TypeParameter::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawTypeParameter* type = reinterpret_cast<RawTypeParameter*>(d->Ref(id));
+ Deserializer::InitializeHeader(type, kTypeParameterCid,
+ TypeParameter::InstanceSize(),
+ is_vm_object);
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ type->ptr()->parameterized_class_id_ = d->Read<intptr_t>();
+ type->ptr()->token_pos_ = d->ReadTokenPosition();
+ type->ptr()->index_ = d->Read<int16_t>();
+ type->ptr()->type_state_ = d->Read<int8_t>();
+ }
+ }
+};
+
+
+class BoundedTypeSerializationCluster : public SerializationCluster {
+ public:
+ BoundedTypeSerializationCluster() { }
+ virtual ~BoundedTypeSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawBoundedType* type = BoundedType::RawCast(object);
+ objects_.Add(type);
+
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kBoundedTypeCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawBoundedType* type = objects_[i];
+ s->AssignRef(type);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawBoundedType* type = objects_[i];
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawBoundedType*> objects_;
+};
+
+
+class BoundedTypeDeserializationCluster : public DeserializationCluster {
+ public:
+ BoundedTypeDeserializationCluster() { }
+ virtual ~BoundedTypeDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ BoundedType::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawBoundedType* type = reinterpret_cast<RawBoundedType*>(d->Ref(id));
+ Deserializer::InitializeHeader(type, kBoundedTypeCid,
+ BoundedType::InstanceSize(), is_vm_object);
+ RawObject** from = type->from();
+ RawObject** to = type->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class ClosureSerializationCluster : public SerializationCluster {
+ public:
+ ClosureSerializationCluster() { }
+ virtual ~ClosureSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawClosure* closure = Closure::RawCast(object);
+ objects_.Add(closure);
+
+ RawObject** from = closure->from();
+ RawObject** to = closure->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kClosureCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawClosure* closure = objects_[i];
+ s->AssignRef(closure);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawClosure* closure = objects_[i];
+ s->Write<bool>(closure->IsCanonical());
+ RawObject** from = closure->from();
+ RawObject** to = closure->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawClosure*> objects_;
+};
+
+
+class ClosureDeserializationCluster : public DeserializationCluster {
+ public:
+ ClosureDeserializationCluster() { }
+ virtual ~ClosureDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, Closure::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawClosure* closure = reinterpret_cast<RawClosure*>(d->Ref(id));
+ bool is_canonical = d->Read<bool>();
+ Deserializer::InitializeHeader(closure, kClosureCid,
+ Closure::InstanceSize(),
+ is_vm_object, is_canonical);
+ RawObject** from = closure->from();
+ RawObject** to = closure->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class MintSerializationCluster : public SerializationCluster {
+ public:
+ MintSerializationCluster() { }
+ virtual ~MintSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawMint* mint = Mint::RawCast(object);
+ objects_.Add(mint);
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kMintCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawMint* mint = objects_[i];
+ s->AssignRef(mint);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawMint* mint = objects_[i];
+ s->Write<bool>(mint->IsCanonical());
+ s->Write<int64_t>(mint->ptr()->value_);
+ }
+ }
+
+ private:
+ GrowableArray<RawMint*> objects_;
+};
+
+
+class MintDeserializationCluster : public DeserializationCluster {
+ public:
+ MintDeserializationCluster() { }
+ virtual ~MintDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, Mint::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawMint* mint = reinterpret_cast<RawMint*>(d->Ref(id));
+ bool is_canonical = d->Read<bool>();
+ Deserializer::InitializeHeader(mint, kMintCid,
+ Mint::InstanceSize(),
+ is_vm_object, is_canonical);
+ mint->ptr()->value_ = d->Read<int64_t>();
+ }
+ }
+};
+
+
+class BigintSerializationCluster : public SerializationCluster {
+ public:
+ BigintSerializationCluster() { }
+ virtual ~BigintSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawBigint* bigint = Bigint::RawCast(object);
+ objects_.Add(bigint);
+
+ RawObject** from = bigint->from();
+ RawObject** to = bigint->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kBigintCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawBigint* bigint = objects_[i];
+ s->AssignRef(bigint);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawBigint* bigint = objects_[i];
+ s->Write<bool>(bigint->IsCanonical());
+ RawObject** from = bigint->from();
+ RawObject** to = bigint->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawBigint*> objects_;
+};
+
+
+class BigintDeserializationCluster : public DeserializationCluster {
+ public:
+ BigintDeserializationCluster() { }
+ virtual ~BigintDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, Bigint::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawBigint* bigint = reinterpret_cast<RawBigint*>(d->Ref(id));
+ bool is_canonical = d->Read<bool>();
+ Deserializer::InitializeHeader(bigint, kBigintCid,
+ Bigint::InstanceSize(),
+ is_vm_object, is_canonical);
+ RawObject** from = bigint->from();
+ RawObject** to = bigint->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class DoubleSerializationCluster : public SerializationCluster {
+ public:
+ DoubleSerializationCluster() { }
+ virtual ~DoubleSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawDouble* dbl = Double::RawCast(object);
+ objects_.Add(dbl);
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kDoubleCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawDouble* dbl = objects_[i];
+ s->AssignRef(dbl);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawDouble* dbl = objects_[i];
+ s->Write<bool>(dbl->IsCanonical());
+ s->Write<double>(dbl->ptr()->value_);
+ }
+ }
+
+ private:
+ GrowableArray<RawDouble*> objects_;
+};
+
+
+class DoubleDeserializationCluster : public DeserializationCluster {
+ public:
+ DoubleDeserializationCluster() { }
+ virtual ~DoubleDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space, Double::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawDouble* dbl = reinterpret_cast<RawDouble*>(d->Ref(id));
+ bool is_canonical = d->Read<bool>();
+ Deserializer::InitializeHeader(dbl, kDoubleCid,
+ Double::InstanceSize(),
+ is_vm_object, is_canonical);
+ dbl->ptr()->value_ = d->Read<double>();
+ }
+ }
+};
+
+
+class GrowableObjectArraySerializationCluster : public SerializationCluster {
+ public:
+ GrowableObjectArraySerializationCluster() { }
+ virtual ~GrowableObjectArraySerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawGrowableObjectArray* array = GrowableObjectArray::RawCast(object);
+ objects_.Add(array);
+
+ RawObject** from = array->from();
+ RawObject** to = array->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kGrowableObjectArrayCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawGrowableObjectArray* array = objects_[i];
+ s->AssignRef(array);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawGrowableObjectArray* array = objects_[i];
+ s->Write<bool>(array->IsCanonical());
+ RawObject** from = array->from();
+ RawObject** to = array->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawGrowableObjectArray*> objects_;
+};
+
+
+class GrowableObjectArrayDeserializationCluster
+ : public DeserializationCluster {
+ public:
+ GrowableObjectArrayDeserializationCluster() { }
+ virtual ~GrowableObjectArrayDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ GrowableObjectArray::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawGrowableObjectArray* list =
+ reinterpret_cast<RawGrowableObjectArray*>(d->Ref(id));
+ bool is_canonical = d->Read<bool>();
+ Deserializer::InitializeHeader(list, kGrowableObjectArrayCid,
+ GrowableObjectArray::InstanceSize(),
+ is_vm_object, is_canonical);
+ RawObject** from = list->from();
+ RawObject** to = list->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class TypedDataSerializationCluster : public SerializationCluster {
+ public:
+ explicit TypedDataSerializationCluster(intptr_t cid) : cid_(cid) { }
+ virtual ~TypedDataSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawTypedData* data = TypedData::RawCast(object);
+ objects_.Add(data);
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->Write<intptr_t>(cid_);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawTypedData* data = objects_[i];
+ intptr_t length = Smi::Value(data->ptr()->length_);
+ s->Write<intptr_t>(length);
+ s->AssignRef(data);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+ for (intptr_t i = 0; i < count; i++) {
+ RawTypedData* data = objects_[i];
+ intptr_t length = Smi::Value(data->ptr()->length_);
+ s->Write<intptr_t>(length);
+ s->Write<bool>(data->IsCanonical());
+ uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data());
+ s->WriteBytes(cdata, length * element_size);
+ }
+ }
+
+ private:
+ const intptr_t cid_;
+ GrowableArray<RawTypedData*> objects_;
+};
+
+
+class TypedDataDeserializationCluster : public DeserializationCluster {
+ public:
+ explicit TypedDataDeserializationCluster(intptr_t cid) : cid_(cid) { }
+ virtual ~TypedDataDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->Read<intptr_t>();
+ d->AssignRef(AllocateUninitialized(old_space,
+ TypedData::InstanceSize(length * element_size)));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+ intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawTypedData* data = reinterpret_cast<RawTypedData*>(d->Ref(id));
+ intptr_t length = d->Read<intptr_t>();
+ bool is_canonical = d->Read<bool>();
+ intptr_t length_in_bytes = length * element_size;
+ Deserializer::InitializeHeader(data, cid_,
+ TypedData::InstanceSize(length_in_bytes),
+ is_vm_object, is_canonical);
+ data->ptr()->length_ = Smi::New(length);
+ uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data());
+ d->ReadBytes(cdata, length_in_bytes);
+ }
+ }
+
+ private:
+ const intptr_t cid_;
+};
+
+
+class ExternalTypedDataSerializationCluster : public SerializationCluster {
+ public:
+ explicit ExternalTypedDataSerializationCluster(intptr_t cid) : cid_(cid) { }
+ virtual ~ExternalTypedDataSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawExternalTypedData* data = ExternalTypedData::RawCast(object);
+ objects_.Add(data);
+ ASSERT(!data->IsCanonical());
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->Write<intptr_t>(cid_);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawExternalTypedData* data = objects_[i];
+ s->AssignRef(data);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+ for (intptr_t i = 0; i < count; i++) {
+ RawExternalTypedData* data = objects_[i];
+ intptr_t length = Smi::Value(data->ptr()->length_);
+ s->Write<intptr_t>(length);
+ uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data_);
+ s->WriteBytes(cdata, length * element_size);
+ }
+ }
+
+ private:
+ const intptr_t cid_;
+ GrowableArray<RawExternalTypedData*> objects_;
+};
+
+
+class ExternalTypedDataDeserializationCluster : public DeserializationCluster {
+ public:
+ explicit ExternalTypedDataDeserializationCluster(intptr_t cid) : cid_(cid) { }
+ virtual ~ExternalTypedDataDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ ExternalTypedData::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+ intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawExternalTypedData* data =
+ reinterpret_cast<RawExternalTypedData*>(d->Ref(id));
+ intptr_t length = d->Read<intptr_t>();
+ Deserializer::InitializeHeader(data, cid_,
+ ExternalTypedData::InstanceSize(),
+ is_vm_object);
+ data->ptr()->length_ = Smi::New(length);
+ data->ptr()->data_ = const_cast<uint8_t*>(d->CurrentBufferAddress());
+ d->Advance(length * element_size);
+ }
+ }
+
+ private:
+ const intptr_t cid_;
+};
+
+
+class StacktraceSerializationCluster : public SerializationCluster {
+ public:
+ StacktraceSerializationCluster() { }
+ virtual ~StacktraceSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawStacktrace* trace = Stacktrace::RawCast(object);
+ objects_.Add(trace);
+
+ RawObject** from = trace->from();
+ RawObject** to = trace->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kStacktraceCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawStacktrace* trace = objects_[i];
+ s->AssignRef(trace);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawStacktrace* trace = objects_[i];
+ RawObject** from = trace->from();
+ RawObject** to = trace->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawStacktrace*> objects_;
+};
+
+
+class StacktraceDeserializationCluster : public DeserializationCluster {
+ public:
+ StacktraceDeserializationCluster() { }
+ virtual ~StacktraceDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ Stacktrace::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawStacktrace* trace = reinterpret_cast<RawStacktrace*>(d->Ref(id));
+ Deserializer::InitializeHeader(trace, kStacktraceCid,
+ Stacktrace::InstanceSize(), is_vm_object);
+ RawObject** from = trace->from();
+ RawObject** to = trace->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+ }
+ }
+};
+
+
+class RegExpSerializationCluster : public SerializationCluster {
+ public:
+ RegExpSerializationCluster() { }
+ virtual ~RegExpSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawRegExp* regexp = RegExp::RawCast(object);
+ objects_.Add(regexp);
+
+ RawObject** from = regexp->from();
+ RawObject** to = regexp->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->Push(*p);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kRegExpCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawRegExp* regexp = objects_[i];
+ s->AssignRef(regexp);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawRegExp* regexp = objects_[i];
+ RawObject** from = regexp->from();
+ RawObject** to = regexp->to();
+ for (RawObject** p = from; p <= to; p++) {
+ s->WriteRef(*p);
+ }
+
+ s->Write<intptr_t>(regexp->ptr()->num_registers_);
+ s->Write<int8_t>(regexp->ptr()->type_flags_);
+ }
+ }
+
+ private:
+ GrowableArray<RawRegExp*> objects_;
+};
+
+
+class RegExpDeserializationCluster : public DeserializationCluster {
+ public:
+ RegExpDeserializationCluster() { }
+ virtual ~RegExpDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ RegExp::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawRegExp* regexp = reinterpret_cast<RawRegExp*>(d->Ref(id));
+ Deserializer::InitializeHeader(regexp, kRegExpCid,
+ RegExp::InstanceSize(), is_vm_object);
+ RawObject** from = regexp->from();
+ RawObject** to = regexp->to();
+ for (RawObject** p = from; p <= to; p++) {
+ *p = d->ReadRef();
+ }
+
+ regexp->ptr()->num_registers_ = d->Read<intptr_t>();
+ regexp->ptr()->type_flags_ = d->Read<int8_t>();
+ }
+ }
+};
+
+
+class LinkedHashMapSerializationCluster : public SerializationCluster {
+ public:
+ LinkedHashMapSerializationCluster() { }
+ virtual ~LinkedHashMapSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawLinkedHashMap* map = LinkedHashMap::RawCast(object);
+ objects_.Add(map);
+
+ s->Push(map->ptr()->type_arguments_);
+
+ intptr_t used_data = Smi::Value(map->ptr()->used_data_);
+ RawArray* data_array = map->ptr()->data_;
+ RawObject** data_elements = data_array->ptr()->data();
+ for (intptr_t i = 0; i < used_data; i += 2) {
+ RawObject* key = data_elements[i];
+ if (key != data_array) {
+ RawObject* value = data_elements[i + 1];
+ s->Push(key);
+ s->Push(value);
+ }
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kLinkedHashMapCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawLinkedHashMap* map = objects_[i];
+ s->AssignRef(map);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawLinkedHashMap* map = objects_[i];
+ s->Write<bool>(map->IsCanonical());
+
+ s->WriteRef(map->ptr()->type_arguments_);
+
+ const intptr_t used_data = Smi::Value(map->ptr()->used_data_);
+ ASSERT((used_data & 1) == 0); // Keys + values, so must be even.
+ const intptr_t deleted_keys = Smi::Value(map->ptr()->deleted_keys_);
+
+ // Write out the number of (not deleted) key/value pairs that will follow.
+ s->Write<intptr_t>((used_data >> 1) - deleted_keys);
+
+ RawArray* data_array = map->ptr()->data_;
+ RawObject** data_elements = data_array->ptr()->data();
+ for (intptr_t i = 0; i < used_data; i += 2) {
+ RawObject* key = data_elements[i];
+ if (key != data_array) {
+ RawObject* value = data_elements[i + 1];
+ s->WriteRef(key);
+ s->WriteRef(value);
+ }
+ }
+ }
+ }
+
+ private:
+ GrowableArray<RawLinkedHashMap*> objects_;
+};
+
+
+class LinkedHashMapDeserializationCluster : public DeserializationCluster {
+ public:
+ LinkedHashMapDeserializationCluster() { }
+ virtual ~LinkedHashMapDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ d->AssignRef(AllocateUninitialized(old_space,
+ LinkedHashMap::InstanceSize()));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+ PageSpace* old_space = d->heap()->old_space();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawLinkedHashMap* map = reinterpret_cast<RawLinkedHashMap*>(d->Ref(id));
+ bool is_canonical = d->Read<bool>();
+ Deserializer::InitializeHeader(map, kLinkedHashMapCid,
+ LinkedHashMap::InstanceSize(),
+ is_vm_object, is_canonical);
+
+ map->ptr()->type_arguments_ =
+ reinterpret_cast<RawTypeArguments*>(d->ReadRef());
+
+ // TODO(rmacnak): Reserve ref ids and co-allocate in ReadAlloc.
+ intptr_t pairs = d->Read<intptr_t>();
+ intptr_t used_data = pairs << 1;
+ intptr_t data_size = Utils::Maximum(
+ Utils::RoundUpToPowerOfTwo(used_data),
+ static_cast<uintptr_t>(LinkedHashMap::kInitialIndexSize));
+
+ RawArray* data = reinterpret_cast<RawArray*>(
+ AllocateUninitialized(old_space, Array::InstanceSize(data_size)));
+ data->ptr()->type_arguments_ = TypeArguments::null();
+ data->ptr()->length_ = Smi::New(data_size);
+ intptr_t i;
+ for (i = 0; i < used_data; i++) {
+ data->ptr()->data()[i] = d->ReadRef();
+ }
+ for (; i < data_size; i++) {
+ data->ptr()->data()[i] = Object::null();
+ }
+
+ map->ptr()->index_ = TypedData::null();
+ map->ptr()->hash_mask_ = Smi::New(0);
+ map->ptr()->data_ = data;
+ map->ptr()->used_data_ = Smi::New(used_data);
+ map->ptr()->deleted_keys_ = Smi::New(0);
+ }
+ }
+};
+
+
+class ArraySerializationCluster : public SerializationCluster {
+ public:
+ explicit ArraySerializationCluster(intptr_t cid) : cid_(cid) { }
+ virtual ~ArraySerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawArray* array = Array::RawCast(object);
+ objects_.Add(array);
+
+ s->Push(array->ptr()->type_arguments_);
+ intptr_t length = Smi::Value(array->ptr()->length_);
+ for (intptr_t i = 0; i < length; i++) {
+ s->Push(array->ptr()->data()[i]);
+ }
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(cid_);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawArray* array = objects_[i];
+ intptr_t length = Smi::Value(array->ptr()->length_);
+ s->Write<intptr_t>(length);
+ s->AssignRef(array);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawArray* array = objects_[i];
+ intptr_t length = Smi::Value(array->ptr()->length_);
+ s->Write<intptr_t>(length);
+ s->Write<bool>(array->IsCanonical());
+ s->WriteRef(array->ptr()->type_arguments_);
+ for (intptr_t j = 0; j < length; j++) {
+ s->WriteRef(array->ptr()->data()[j]);
+ }
+ }
+ }
+
+ private:
+ intptr_t cid_;
+ GrowableArray<RawArray*> objects_;
+};
+
+
+class ArrayDeserializationCluster : public DeserializationCluster {
+ public:
+ explicit ArrayDeserializationCluster(intptr_t cid) : cid_(cid) { }
+ virtual ~ArrayDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->Read<intptr_t>();
+ d->AssignRef(AllocateUninitialized(old_space,
+ Array::InstanceSize(length)));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawArray* array = reinterpret_cast<RawArray*>(d->Ref(id));
+ intptr_t length = d->Read<intptr_t>();
+ bool is_canonical = d->Read<bool>();
+ Deserializer::InitializeHeader(array, cid_,
+ Array::InstanceSize(length),
+ is_vm_object, is_canonical);
+ array->ptr()->type_arguments_ =
+ reinterpret_cast<RawTypeArguments*>(d->ReadRef());
+ array->ptr()->length_ = Smi::New(length);
+ for (intptr_t j = 0; j < length; j++) {
+ array->ptr()->data()[j] = d->ReadRef();
+ }
+ }
+ }
+
+ private:
+ const intptr_t cid_;
+};
+
+
+class OneByteStringSerializationCluster : public SerializationCluster {
+ public:
+ OneByteStringSerializationCluster() { }
+ virtual ~OneByteStringSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawOneByteString* str = reinterpret_cast<RawOneByteString*>(object);
+ objects_.Add(str);
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kOneByteStringCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawOneByteString* str = objects_[i];
+ intptr_t length = Smi::Value(str->ptr()->length_);
+ s->Write<intptr_t>(length);
+ s->AssignRef(str);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawOneByteString* str = objects_[i];
+ intptr_t length = Smi::Value(str->ptr()->length_);
+ s->Write<intptr_t>(length);
+ s->Write<bool>(str->IsCanonical());
+ intptr_t hash = Smi::Value(str->ptr()->hash_);
+ s->Write<int32_t>(hash);
+ s->WriteBytes(str->ptr()->data(), length);
+ }
+ }
+
+ private:
+ GrowableArray<RawOneByteString*> objects_;
+};
+
+
+class OneByteStringDeserializationCluster : public DeserializationCluster {
+ public:
+ OneByteStringDeserializationCluster() { }
+ virtual ~OneByteStringDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->Read<intptr_t>();
+ d->AssignRef(AllocateUninitialized(old_space,
+ OneByteString::InstanceSize(length)));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawOneByteString* str = reinterpret_cast<RawOneByteString*>(d->Ref(id));
+ intptr_t length = d->Read<intptr_t>();
+ bool is_canonical = d->Read<bool>();
+ Deserializer::InitializeHeader(str, kOneByteStringCid,
+ OneByteString::InstanceSize(length),
+ is_vm_object, is_canonical);
+ str->ptr()->length_ = Smi::New(length);
+ str->ptr()->hash_ = Smi::New(d->Read<intptr_t>());
+ for (intptr_t j = 0; j < length; j++) {
+ str->ptr()->data()[j] = d->Read<uint8_t>();
+ }
+ }
+ }
+};
+
+
+class TwoByteStringSerializationCluster : public SerializationCluster {
+ public:
+ TwoByteStringSerializationCluster() { }
+ virtual ~TwoByteStringSerializationCluster() { }
+
+ void Trace(Serializer* s, RawObject* object) {
+ RawTwoByteString* str = reinterpret_cast<RawTwoByteString*>(object);
+ objects_.Add(str);
+ }
+
+ void WriteAlloc(Serializer* s) {
+ s->WriteCid(kTwoByteStringCid);
+ intptr_t count = objects_.length();
+ s->Write<intptr_t>(count);
+ for (intptr_t i = 0; i < count; i++) {
+ RawTwoByteString* str = objects_[i];
+ intptr_t length = Smi::Value(str->ptr()->length_);
+ s->Write<intptr_t>(length);
+ s->AssignRef(str);
+ }
+ }
+
+ void WriteFill(Serializer* s) {
+ intptr_t count = objects_.length();
+ for (intptr_t i = 0; i < count; i++) {
+ RawTwoByteString* str = objects_[i];
+ intptr_t length = Smi::Value(str->ptr()->length_);
+ s->Write<intptr_t>(length);
+ s->Write<bool>(str->IsCanonical());
+ intptr_t hash = Smi::Value(str->ptr()->hash_);
+ s->Write<int32_t>(hash);
+ s->WriteBytes(reinterpret_cast<uint8_t*>(str->ptr()->data()), length * 2);
+ }
+ }
+
+ private:
+ GrowableArray<RawTwoByteString*> objects_;
+};
+
+
+class TwoByteStringDeserializationCluster : public DeserializationCluster {
+ public:
+ TwoByteStringDeserializationCluster() { }
+ virtual ~TwoByteStringDeserializationCluster() { }
+
+ void ReadAlloc(Deserializer* d) {
+ start_index_ = d->next_index();
+ PageSpace* old_space = d->heap()->old_space();
+ intptr_t count = d->Read<intptr_t>();
+ for (intptr_t i = 0; i < count; i++) {
+ intptr_t length = d->Read<intptr_t>();
+ d->AssignRef(AllocateUninitialized(old_space,
+ TwoByteString::InstanceSize(length)));
+ }
+ stop_index_ = d->next_index();
+ }
+
+ void ReadFill(Deserializer* d) {
+ bool is_vm_object = d->isolate() == Dart::vm_isolate();
+
+ for (intptr_t id = start_index_; id < stop_index_; id++) {
+ RawTwoByteString* str =
+ reinterpret_cast<RawTwoByteString*>(d->Ref(id));
+ intptr_t length = d->Read<intptr_t>();
+ bool is_canonical = d->Read<bool>();
+ Deserializer::InitializeHeader(str, kTwoByteStringCid,
+ TwoByteString::InstanceSize(length),
+ is_vm_object, is_canonical);
+ str->ptr()->length_ = Smi::New(length);
+ str->ptr()->hash_ = Smi::New(d->Read<int32_t>());
+ uint8_t* cdata = reinterpret_cast<uint8_t*>(str->ptr()->data());
+ d->ReadBytes(cdata, length * 2);
+ }
+ }
+};
+
+
+Serializer::Serializer(Thread* thread,
+ Snapshot::Kind kind,
+ uint8_t** buffer,
+ ReAlloc alloc,
+ intptr_t initial_size,
+ InstructionsWriter* instructions_writer)
+ : StackResource(thread),
+ heap_(thread->isolate()->heap()),
+ zone_(thread->zone()),
+ kind_(kind),
+ stream_(buffer, alloc, initial_size),
+ instructions_writer_(instructions_writer),
+ clusters_by_cid_(NULL),
+ stack_(),
+ num_cids_(0),
+ num_base_objects_(0),
+ num_written_objects_(0),
+ next_ref_index_(1) {
+ num_cids_ = thread->isolate()->class_table()->NumCids();
+ clusters_by_cid_ = new SerializationCluster*[num_cids_];
+ for (intptr_t i = 0; i < num_cids_; i++) {
+ clusters_by_cid_[i] = NULL;
+ }
+}
+
+
+Serializer::~Serializer() {
+ delete[] clusters_by_cid_;
+}
+
+
+SerializationCluster* Serializer::NewClusterForClass(intptr_t cid) {
+ Zone* Z = zone_;
+ if ((cid > kNumPredefinedCids) ||
+ (cid == kInstanceCid) ||
+ RawObject::IsTypedDataViewClassId(cid)) {
+ Push(isolate()->class_table()->At(cid));
+ return new (Z) InstanceSerializationCluster(cid);
+ }
+ if (RawObject::IsExternalTypedDataClassId(cid)) {
+ return new (Z) ExternalTypedDataSerializationCluster(cid);
+ }
+ if (RawObject::IsTypedDataClassId(cid)) {
+ return new (Z) TypedDataSerializationCluster(cid);
+ }
+
+ switch (cid) {
+ case kClassCid: return new (Z) ClassSerializationCluster(num_cids_);
+ case kUnresolvedClassCid:
+ return new (Z) UnresolvedClassSerializationCluster();
+ case kTypeArgumentsCid: return new (Z) TypeArgumentsSerializationCluster();
+ case kPatchClassCid: return new (Z) PatchClassSerializationCluster();
+ case kFunctionCid: return new (Z) FunctionSerializationCluster();
+ case kClosureDataCid: return new (Z) ClosureDataSerializationCluster();
+ case kRedirectionDataCid:
+ return new (Z) RedirectionDataSerializationCluster();
+ case kFieldCid: return new (Z) FieldSerializationCluster();
+ case kLiteralTokenCid: return new (Z) LiteralTokenSerializationCluster();
+ case kTokenStreamCid: return new (Z) TokenStreamSerializationCluster();
+ case kScriptCid: return new (Z) ScriptSerializationCluster();
+ case kLibraryCid: return new (Z) LibrarySerializationCluster();
+ case kNamespaceCid: return new (Z) NamespaceSerializationCluster();
+ case kCodeCid: return new (Z) CodeSerializationCluster();
+ case kObjectPoolCid: return new (Z) ObjectPoolSerializationCluster();
+ case kPcDescriptorsCid:
+ return new (Z) RODataSerializationCluster(kPcDescriptorsCid);
+ case kStackmapCid:
+ return new (Z) RODataSerializationCluster(kStackmapCid);
+ case kExceptionHandlersCid:
+ return new (Z) ExceptionHandlersSerializationCluster();
+ case kContextCid: return new (Z) ContextSerializationCluster();
+ case kContextScopeCid: return new (Z) ContextScopeSerializationCluster();
+ case kICDataCid: return new (Z) ICDataSerializationCluster();
+ case kMegamorphicCacheCid:
+ return new (Z) MegamorphicCacheSerializationCluster();
+ case kSubtypeTestCacheCid:
+ return new (Z) SubtypeTestCacheSerializationCluster();
+ case kLanguageErrorCid:
+ return new (Z) LanguageErrorSerializationCluster();
+ case kUnhandledExceptionCid:
+ return new (Z) UnhandledExceptionSerializationCluster();
+ case kLibraryPrefixCid: return new (Z) LibraryPrefixSerializationCluster();
+ case kTypeCid: return new (Z) TypeSerializationCluster();
+ case kTypeRefCid: return new (Z) TypeRefSerializationCluster();
+ case kTypeParameterCid: return new (Z) TypeParameterSerializationCluster();
+ case kBoundedTypeCid: return new (Z) BoundedTypeSerializationCluster();
+ case kClosureCid: return new (Z) ClosureSerializationCluster();
+ case kMintCid: return new (Z) MintSerializationCluster();
+ case kBigintCid: return new (Z) BigintSerializationCluster();
+ case kDoubleCid: return new (Z) DoubleSerializationCluster();
+ case kGrowableObjectArrayCid:
+ return new (Z) GrowableObjectArraySerializationCluster();
+ case kStacktraceCid: return new (Z) StacktraceSerializationCluster();
+ case kRegExpCid: return new (Z) RegExpSerializationCluster();
+ case kLinkedHashMapCid: return new (Z) LinkedHashMapSerializationCluster();
+ case kArrayCid:
+ return new (Z) ArraySerializationCluster(kArrayCid);
+ case kImmutableArrayCid:
+ return new (Z) ArraySerializationCluster(kImmutableArrayCid);
+ case kOneByteStringCid: {
+ if (Snapshot::IncludesCode(kind_)) {
+ return new (Z) RODataSerializationCluster(kOneByteStringCid);
+ } else {
+ return new (Z) OneByteStringSerializationCluster();
+ }
+ }
+ case kTwoByteStringCid: {
+ if (Snapshot::IncludesCode(kind_)) {
+ return new (Z) RODataSerializationCluster(kTwoByteStringCid);
+ } else {
+ return new (Z) TwoByteStringSerializationCluster();
+ }
+ }
+ default: break;
+ }
+
+ FATAL1("No cluster defined for cid %" Pd, cid);
+ return NULL;
+}
+
+
+void Serializer::Trace(RawObject* object) {
+ intptr_t cid;
+ if (!object->IsHeapObject()) {
+ cid = kSmiCid;
+ } else {
+ cid = object->GetClassId();
+ }
+
+ SerializationCluster* cluster = clusters_by_cid_[cid];
+ if (cluster == NULL) {
+ cluster = NewClusterForClass(cid);
+ clusters_by_cid_[cid] = cluster;
+ }
+ ASSERT(cluster != NULL);
+ cluster->Trace(this, object);
+}
+
+
+void Serializer::WriteVersionAndFeatures() {
+ const char* expected_version = Version::SnapshotString();
+ ASSERT(expected_version != NULL);
+ const intptr_t version_len = strlen(expected_version);
+ WriteBytes(reinterpret_cast<const uint8_t*>(expected_version), version_len);
+
+ const char* expected_features = Dart::FeaturesString(kind_);
+ ASSERT(expected_features != NULL);
+ const intptr_t features_len = strlen(expected_features);
+ WriteBytes(reinterpret_cast<const uint8_t*>(expected_features),
+ features_len + 1);
+ free(const_cast<char*>(expected_features));
+}
+
+
+#if defined(DEBUG)
+static const intptr_t kSectionMarker = 0xABAB;
+#endif
+
+void Serializer::Serialize() {
+ while (stack_.length() > 0) {
+ Trace(stack_.RemoveLast());
+ }
+
+ intptr_t num_clusters = 0;
+ for (intptr_t cid = 1; cid < num_cids_; cid++) {
+ SerializationCluster* cluster = clusters_by_cid_[cid];
+ if (cluster != NULL) {
+ num_clusters++;
+ }
+ }
+
+ intptr_t num_objects = num_base_objects_ + num_written_objects_;
+
+ Write<int32_t>(num_objects);
+ Write<int32_t>(num_clusters);
+
+ for (intptr_t cid = 1; cid < num_cids_; cid++) {
+ SerializationCluster* cluster = clusters_by_cid_[cid];
+ if (cluster != NULL) {
+ cluster->WriteAlloc(this);
+#if defined(DEBUG)
+ Write<intptr_t>(next_ref_index_);
+#endif
+ }
+ }
+
+ // We should have assigned a ref to every object we pushed.
+ ASSERT((next_ref_index_ - 1) == num_objects);
+
+ for (intptr_t cid = 1; cid < num_cids_; cid++) {
+ SerializationCluster* cluster = clusters_by_cid_[cid];
+ if (cluster != NULL) {
+ cluster->WriteFill(this);
+#if defined(DEBUG)
+ Write<intptr_t>(kSectionMarker);
+#endif
+ }
+ }
+}
+
+
+void Serializer::AddVMIsolateBaseObjects() {
+ // These objects are always allocated by Object::InitOnce, so they are not
+ // written into the snapshot.
+
+ AddBaseObject(Object::null());
+ AddBaseObject(Object::sentinel().raw());
+ AddBaseObject(Object::transition_sentinel().raw());
+ AddBaseObject(Object::empty_array().raw());
+ AddBaseObject(Object::zero_array().raw());
+ AddBaseObject(Object::dynamic_type().raw());
+ AddBaseObject(Object::void_type().raw());
+ AddBaseObject(Bool::True().raw());
+ AddBaseObject(Bool::False().raw());
+ AddBaseObject(Object::extractor_parameter_types().raw());
+ AddBaseObject(Object::extractor_parameter_names().raw());
+ AddBaseObject(Object::empty_context_scope().raw());
+ AddBaseObject(Object::empty_descriptors().raw());
+ AddBaseObject(Object::empty_var_descriptors().raw());
+ AddBaseObject(Object::empty_exception_handlers().raw());
+
+ for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
+ AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i]);
+ }
+ for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
+ AddBaseObject(ICData::cached_icdata_arrays_[i]);
+ }
+
+ ClassTable* table = isolate()->class_table();
+ for (intptr_t cid = kClassCid; cid <= kUnwindErrorCid; cid++) {
+ // Error has no class object.
+ if (cid != kErrorCid) {
+ ASSERT(table->HasValidClassAt(cid));
+ AddBaseObject(table->At(cid));
+ }
+ }
+ AddBaseObject(table->At(kDynamicCid));
+ AddBaseObject(table->At(kVoidCid));
+}
+
+
+intptr_t Serializer::WriteVMSnapshot(const Array& symbols,
+ const Array& scripts) {
+ NoSafepointScope no_safepoint;
+
+ AddVMIsolateBaseObjects();
+
+ // Push roots.
+ Push(symbols.raw());
+ Push(scripts.raw());
+ if (Snapshot::IncludesCode(kind_)) {
+ StubCode::Push(this);
+ }
+
+ Serialize();
+
+ // Write roots.
+ WriteRef(symbols.raw());
+ WriteRef(scripts.raw());
+ if (Snapshot::IncludesCode(kind_)) {
+ StubCode::WriteRef(this);
+ }
+
+#if defined(DEBUG)
+ Write<intptr_t>(kSectionMarker);
+#endif
+
+ // Note we are not clearing the object id table. The full ref table
+ // of the vm isolate snapshot serves as the base objects for the
+ // regular isolate snapshot.
+
+ // Return the number of objects, -1 accounts for unused ref 0.
+ return next_ref_index_ - 1;
+}
+
+
+void Serializer::WriteFullSnapshot(intptr_t num_base_objects,
+ ObjectStore* object_store) {
+ NoSafepointScope no_safepoint;
+
+ if (num_base_objects == 0) {
+ // Units tests not writing a new vm isolate.
+ const Array& base_objects = Object::vm_isolate_snapshot_object_table();
+ for (intptr_t i = 1; i < base_objects.Length(); i++) {
+ AddBaseObject(base_objects.At(i));
+ }
+ } else {
+ // Base objects carried over from WriteVMIsolateSnapshot.
+ num_base_objects_ += num_base_objects;
+ next_ref_index_ += num_base_objects;
+ }
+
+ // Push roots.
+ RawObject** from = object_store->from();
+ RawObject** to = object_store->to_snapshot(kind_);
+ for (RawObject** p = from; p <= to; p++) {
+ Push(*p);
+ }
+
+ Serialize();
+
+ // Write roots.
+ for (RawObject** p = from; p <= to; p++) {
+ WriteRef(*p);
+ }
+
+#if defined(DEBUG)
+ Write<intptr_t>(kSectionMarker);
+#endif
+
+ heap_->ResetObjectIdTable();
+}
+
+
+Deserializer::Deserializer(Thread* thread,
+ Snapshot::Kind kind,
+ const uint8_t* buffer,
+ intptr_t size,
+ const uint8_t* instructions_buffer,
+ const uint8_t* data_buffer)
+ : StackResource(thread),
+ heap_(thread->isolate()->heap()),
+ zone_(thread->zone()),
+ kind_(kind),
+ stream_(buffer, size),
+ instructions_reader_(NULL),
+ refs_(NULL),
+ next_ref_index_(1),
+ clusters_(NULL) {
+ if (Snapshot::IncludesCode(kind)) {
+ ASSERT(instructions_buffer != NULL);
+ }
+ if (instructions_buffer != NULL) {
+ instructions_reader_ =
+ new (zone_) InstructionsReader(instructions_buffer, data_buffer);
+ }
+}
+
+
+Deserializer::~Deserializer() {
+ delete[] clusters_;
+}
+
+
+DeserializationCluster* Deserializer::ReadCluster() {
+ intptr_t cid = ReadCid();
+
+ Zone* Z = zone_;
+ if ((cid > kNumPredefinedCids) ||
+ (cid == kInstanceCid) ||
+ RawObject::IsTypedDataViewClassId(cid)) {
+ return new (Z) InstanceDeserializationCluster(cid);
+ }
+ if (RawObject::IsExternalTypedDataClassId(cid)) {
+ return new (Z) ExternalTypedDataDeserializationCluster(cid);
+ }
+ if (RawObject::IsTypedDataClassId(cid)) {
+ return new (Z) TypedDataDeserializationCluster(cid);
+ }
+
+ switch (cid) {
+ case kClassCid: return new (Z) ClassDeserializationCluster();
+ case kUnresolvedClassCid:
+ return new (Z) UnresolvedClassDeserializationCluster();
+ case kTypeArgumentsCid:
+ return new (Z) TypeArgumentsDeserializationCluster();
+ case kPatchClassCid: return new (Z) PatchClassDeserializationCluster();
+ case kFunctionCid: return new (Z) FunctionDeserializationCluster();
+ case kClosureDataCid: return new (Z) ClosureDataDeserializationCluster();
+ case kRedirectionDataCid:
+ return new (Z) RedirectionDataDeserializationCluster();
+ case kFieldCid: return new (Z) FieldDeserializationCluster();
+ case kLiteralTokenCid: return new (Z) LiteralTokenDeserializationCluster();
+ case kTokenStreamCid: return new (Z) TokenStreamDeserializationCluster();
+ case kScriptCid: return new (Z) ScriptDeserializationCluster();
+ case kLibraryCid: return new (Z) LibraryDeserializationCluster();
+ case kNamespaceCid: return new (Z) NamespaceDeserializationCluster();
+ case kCodeCid: return new (Z) CodeDeserializationCluster();
+ case kObjectPoolCid: return new (Z) ObjectPoolDeserializationCluster();
+ case kPcDescriptorsCid:
+ case kStackmapCid:
+ return new (Z) RODataDeserializationCluster();
+ case kExceptionHandlersCid:
+ return new (Z) ExceptionHandlersDeserializationCluster();
+ case kContextCid: return new (Z) ContextDeserializationCluster();
+ case kContextScopeCid: return new (Z) ContextScopeDeserializationCluster();
+ case kICDataCid: return new (Z) ICDataDeserializationCluster();
+ case kMegamorphicCacheCid:
+ return new (Z) MegamorphicCacheDeserializationCluster();
+ case kSubtypeTestCacheCid:
+ return new (Z) SubtypeTestCacheDeserializationCluster();
+ case kLanguageErrorCid:
+ return new (Z) LanguageErrorDeserializationCluster();
+ case kUnhandledExceptionCid:
+ return new (Z) UnhandledExceptionDeserializationCluster();
+ case kLibraryPrefixCid:
+ return new (Z) LibraryPrefixDeserializationCluster();
+ case kTypeCid: return new (Z) TypeDeserializationCluster();
+ case kTypeRefCid: return new (Z) TypeRefDeserializationCluster();
+ case kTypeParameterCid:
+ return new (Z) TypeParameterDeserializationCluster();
+ case kBoundedTypeCid: return new (Z) BoundedTypeDeserializationCluster();
+ case kClosureCid: return new (Z) ClosureDeserializationCluster();
+ case kMintCid: return new (Z) MintDeserializationCluster();
+ case kBigintCid: return new (Z) BigintDeserializationCluster();
+ case kDoubleCid: return new (Z) DoubleDeserializationCluster();
+ case kGrowableObjectArrayCid:
+ return new (Z) GrowableObjectArrayDeserializationCluster();
+ case kStacktraceCid: return new (Z) StacktraceDeserializationCluster();
+ case kRegExpCid: return new (Z) RegExpDeserializationCluster();
+ case kLinkedHashMapCid:
+ return new (Z) LinkedHashMapDeserializationCluster();
+ case kArrayCid:
+ return new (Z) ArrayDeserializationCluster(kArrayCid);
+ case kImmutableArrayCid:
+ return new (Z) ArrayDeserializationCluster(kImmutableArrayCid);
+ case kOneByteStringCid: {
+ if (Snapshot::IncludesCode(kind_)) {
+ return new (Z) RODataDeserializationCluster();
+ } else {
+ return new (Z) OneByteStringDeserializationCluster();
+ }
+ }
+ case kTwoByteStringCid: {
+ if (Snapshot::IncludesCode(kind_)) {
+ return new (Z) RODataDeserializationCluster();
+ } else {
+ return new (Z) TwoByteStringDeserializationCluster();
+ }
+ }
+ default: break;
+ }
+ FATAL1("No cluster defined for cid %" Pd, cid);
+ return NULL;
+}
+
+
+RawApiError* Deserializer::VerifyVersionAndFeatures() {
+ // If the version string doesn't match, return an error.
+ // Note: New things are allocated only if we're going to return an error.
+
+ const char* expected_version = Version::SnapshotString();
+ ASSERT(expected_version != NULL);
+ const intptr_t version_len = strlen(expected_version);
+ if (PendingBytes() < version_len) {
+ const intptr_t kMessageBufferSize = 128;
+ char message_buffer[kMessageBufferSize];
+ OS::SNPrint(message_buffer,
+ kMessageBufferSize,
+ "No full snapshot version found, expected '%s'",
+ expected_version);
+ // This can also fail while bringing up the VM isolate, so make sure to
+ // allocate the error message in old space.
+ const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
+ return ApiError::New(msg, Heap::kOld);
+ }
+
+ const char* version = reinterpret_cast<const char*>(CurrentBufferAddress());
+ ASSERT(version != NULL);
+ if (strncmp(version, expected_version, version_len)) {
+ const intptr_t kMessageBufferSize = 256;
+ char message_buffer[kMessageBufferSize];
+ char* actual_version = OS::StrNDup(version, version_len);
+ OS::SNPrint(message_buffer,
+ kMessageBufferSize,
+ "Wrong %s snapshot version, expected '%s' found '%s'",
+ (Snapshot::IsFull(kind_)) ? "full" : "script",
+ expected_version,
+ actual_version);
+ free(actual_version);
+ // This can also fail while bringing up the VM isolate, so make sure to
+ // allocate the error message in old space.
+ const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
+ return ApiError::New(msg, Heap::kOld);
+ }
+ Advance(version_len);
+
+ const char* expected_features = Dart::FeaturesString(kind_);
+ ASSERT(expected_features != NULL);
+ const intptr_t expected_len = strlen(expected_features);
+
+ const char* features = reinterpret_cast<const char*>(CurrentBufferAddress());
+ ASSERT(features != NULL);
+ intptr_t buffer_len = OS::StrNLen(features, PendingBytes());
+ if ((buffer_len != expected_len) ||
+ strncmp(features, expected_features, expected_len)) {
+ const intptr_t kMessageBufferSize = 256;
+ char message_buffer[kMessageBufferSize];
+ char* actual_features = OS::StrNDup(features, buffer_len < 128 ? buffer_len
+ : 128);
+ OS::SNPrint(message_buffer,
+ kMessageBufferSize,
+ "Wrong features in snapshot, expected '%s' found '%s'",
+ expected_features,
+ actual_features);
+ free(const_cast<char*>(expected_features));
+ free(actual_features);
+ // This can also fail while bringing up the VM isolate, so make sure to
+ // allocate the error message in old space.
+ const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
+ return ApiError::New(msg, Heap::kOld);
+ }
+ free(const_cast<char*>(expected_features));
+ Advance(expected_len + 1);
+ return ApiError::null();
+}
+
+
+void Deserializer::Prepare() {
+ num_objects_ = Read<int32_t>();
+ num_clusters_ = Read<int32_t>();
+
+ clusters_ = new DeserializationCluster*[num_clusters_];
+ refs_ = Array::New(num_objects_ + 1, Heap::kOld);
+}
+
+
+void Deserializer::Deserialize() {
+ // TODO(rmacnak): Verify num of base objects.
+
+ {
+ NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
+ Timeline::GetIsolateStream(), "ReadAlloc"));
+ for (intptr_t i = 0; i < num_clusters_; i++) {
+ clusters_[i] = ReadCluster();
+ clusters_[i]->ReadAlloc(this);
+#if defined(DEBUG)
+ intptr_t serializers_next_ref_index_ = Read<intptr_t>();
+ ASSERT(serializers_next_ref_index_ == next_ref_index_);
+#endif
+ }
+ }
+
+ // We should have completely filled the ref array.
+ ASSERT((next_ref_index_ - 1) == num_objects_);
+
+ {
+ NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
+ Timeline::GetIsolateStream(), "ReadFill"));
+ for (intptr_t i = 0; i < num_clusters_; i++) {
+ clusters_[i]->ReadFill(this);
+#if defined(DEBUG)
+ intptr_t section_marker = Read<intptr_t>();
+ ASSERT(section_marker == kSectionMarker);
+#endif
+ }
+ }
+}
+
+class HeapLocker : public StackResource {
+ public:
+ HeapLocker(Thread* thread, PageSpace* page_space)
+ : StackResource(thread), page_space_(page_space) {
+ page_space_->AcquireDataLock();
+ }
+ ~HeapLocker() {
+ page_space_->ReleaseDataLock();
+ }
+
+ private:
+ PageSpace* page_space_;
+};
+
+
+void Deserializer::AddVMIsolateBaseObjects() {
+ // These objects are always allocated by Object::InitOnce, so they are not
+ // written into the snapshot.
+
+ AddBaseObject(Object::null());
+ AddBaseObject(Object::sentinel().raw());
+ AddBaseObject(Object::transition_sentinel().raw());
+ AddBaseObject(Object::empty_array().raw());
+ AddBaseObject(Object::zero_array().raw());
+ AddBaseObject(Object::dynamic_type().raw());
+ AddBaseObject(Object::void_type().raw());
+ AddBaseObject(Bool::True().raw());
+ AddBaseObject(Bool::False().raw());
+ AddBaseObject(Object::extractor_parameter_types().raw());
+ AddBaseObject(Object::extractor_parameter_names().raw());
+ AddBaseObject(Object::empty_context_scope().raw());
+ AddBaseObject(Object::empty_descriptors().raw());
+ AddBaseObject(Object::empty_var_descriptors().raw());
+ AddBaseObject(Object::empty_exception_handlers().raw());
+
+ for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
+ AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i]);
+ }
+ for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
+ AddBaseObject(ICData::cached_icdata_arrays_[i]);
+ }
+
+ ClassTable* table = isolate()->class_table();
+ for (intptr_t cid = kClassCid; cid <= kUnwindErrorCid; cid++) {
+ // Error has no class object.
+ if (cid != kErrorCid) {
+ ASSERT(table->HasValidClassAt(cid));
+ AddBaseObject(table->At(cid));
+ }
+ }
+ AddBaseObject(table->At(kDynamicCid));
+ AddBaseObject(table->At(kVoidCid));
+}
+
+
+void Deserializer::ReadVMSnapshot() {
+ Array& symbol_table = Array::Handle(zone_);
+ Array& refs = Array::Handle(zone_);
+ Prepare();
+
+ {
+ NoSafepointScope no_safepoint;
+ HeapLocker hl(thread(), heap_->old_space());
+
+ AddVMIsolateBaseObjects();
+
+ Deserialize();
+
+ // Read roots.
+ symbol_table ^= ReadRef();
+ isolate()->object_store()->set_symbol_table(symbol_table);
+ ReadRef(); // Script list.
+ if (Snapshot::IncludesCode(kind_)) {
+ StubCode::ReadRef(this);
+ }
+
+#if defined(DEBUG)
+ intptr_t section_marker = Read<intptr_t>();
+ ASSERT(section_marker == kSectionMarker);
+#endif
+
+ refs = refs_;
+ refs_ = NULL;
+ }
+
+ Symbols::InitOnceFromSnapshot(isolate());
+
+ Object::set_vm_isolate_snapshot_object_table(refs);
+
+#if defined(DEBUG)
+ isolate()->ValidateClassTable();
+#endif
+}
+
+void Deserializer::ReadFullSnapshot(ObjectStore* object_store) {
+ Array& refs = Array::Handle();
+ Prepare();
+
+ {
+ NoSafepointScope no_safepoint;
+ HeapLocker hl(thread(), heap_->old_space());
+
+ // N.B.: Skipping index 0 because ref 0 is illegal.
+ const Array& base_objects = Object::vm_isolate_snapshot_object_table();
+ for (intptr_t i = 1; i < base_objects.Length(); i++) {
+ AddBaseObject(base_objects.At(i));
+ }
+
+ Deserialize();
+
+ // Read roots.
+ RawObject** from = object_store->from();
+ RawObject** to = object_store->to_snapshot(kind_);
+ for (RawObject** p = from; p <= to; p++) {
+ *p = ReadRef();
+ }
+
+#if defined(DEBUG)
+ intptr_t section_marker = Read<intptr_t>();
+ ASSERT(section_marker == kSectionMarker);
+#endif
+
+ refs = refs_;
+ refs_ = NULL;
+ }
+
+#if defined(DEBUG)
+ Isolate* isolate = thread()->isolate();
+ isolate->ValidateClassTable();
+ isolate->heap()->Verify();
+#endif
+
+ {
+ NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
+ Timeline::GetIsolateStream(), "PostLoad"));
+ for (intptr_t i = 0; i < num_clusters_; i++) {
+ clusters_[i]->PostLoad(refs, kind_, zone_);
+ }
+ }
+
+ // Setup native resolver for bootstrap impl.
+ Bootstrap::SetupNativeResolver();
+}
+
+
+// An object visitor which will iterate over all the script objects in the heap
+// and either count them or collect them into an array. This is used during
+// full snapshot generation of the VM isolate to write out all script
+// objects and their accompanying token streams.
+class ScriptVisitor : public ObjectVisitor {
+ public:
+ explicit ScriptVisitor(Thread* thread) :
+ objHandle_(Object::Handle(thread->zone())),
+ count_(0),
+ scripts_(NULL) {}
+
+ ScriptVisitor(Thread* thread, const Array* scripts) :
+ objHandle_(Object::Handle(thread->zone())),
+ count_(0),
+ scripts_(scripts) {}
+
+ void VisitObject(RawObject* obj) {
+ if (obj->IsScript()) {
+ if (scripts_ != NULL) {
+ objHandle_ = obj;
+ scripts_->SetAt(count_, objHandle_);
+ }
+ count_ += 1;
+ }
+ }
+
+ intptr_t count() const { return count_; }
+
+ private:
+ Object& objHandle_;
+ intptr_t count_;
+ const Array* scripts_;
+};
+
+
+FullSnapshotWriter::FullSnapshotWriter(Snapshot::Kind kind,
+ uint8_t** vm_isolate_snapshot_buffer,
+ uint8_t** isolate_snapshot_buffer,
+ ReAlloc alloc,
+ InstructionsWriter* instructions_writer)
+ : thread_(Thread::Current()),
+ kind_(kind),
+ vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer),
+ isolate_snapshot_buffer_(isolate_snapshot_buffer),
+ alloc_(alloc),
+ vm_isolate_snapshot_size_(0),
+ isolate_snapshot_size_(0),
+ instructions_writer_(instructions_writer),
+ scripts_(Array::Handle(zone())),
+ saved_symbol_table_(Array::Handle(zone())),
+ new_vm_symbol_table_(Array::Handle(zone())) {
+ ASSERT(isolate_snapshot_buffer_ != NULL);
+ ASSERT(alloc_ != NULL);
+ ASSERT(isolate() != NULL);
+ ASSERT(ClassFinalizer::AllClassesFinalized());
+ ASSERT(isolate() != NULL);
+ ASSERT(heap() != NULL);
+ ObjectStore* object_store = isolate()->object_store();
+ ASSERT(object_store != NULL);
+
+#if defined(DEBUG)
+ // Ensure the class table is valid.
+ isolate()->ValidateClassTable();
+#endif
+ // Can't have any mutation happening while we're serializing.
+ ASSERT(isolate()->background_compiler() == NULL);
+
+ if (vm_isolate_snapshot_buffer != NULL) {
+ NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
+ Timeline::GetIsolateStream(), "PrepareNewVMIsolate"));
+
+ // Collect all the script objects and their accompanying token stream
+ // objects into an array so that we can write it out as part of the VM
+ // isolate snapshot. We first count the number of script objects, allocate
+ // an array and then fill it up with the script objects.
+ ScriptVisitor scripts_counter(thread());
+ heap()->IterateOldObjects(&scripts_counter);
+ Dart::vm_isolate()->heap()->IterateOldObjects(&scripts_counter);
+ intptr_t count = scripts_counter.count();
+ scripts_ = Array::New(count, Heap::kOld);
+ ScriptVisitor script_visitor(thread(), &scripts_);
+ heap()->IterateOldObjects(&script_visitor);
+ Dart::vm_isolate()->heap()->IterateOldObjects(&script_visitor);
+ ASSERT(script_visitor.count() == count);
+
+ // Tuck away the current symbol table.
+ saved_symbol_table_ = object_store->symbol_table();
+
+ // Create a unified symbol table that will be written as the vm isolate's
+ // symbol table.
+ new_vm_symbol_table_ = Symbols::UnifiedSymbolTable();
+
+ // Create an empty symbol table that will be written as the isolate's symbol
+ // table.
+ Symbols::SetupSymbolTable(isolate());
+ } else {
+ // Reuse the current vm isolate.
+ }
+}
+
+FullSnapshotWriter::~FullSnapshotWriter() {
+ // We may run Dart code afterwards, restore the symbol table if needed.
+ if (!saved_symbol_table_.IsNull()) {
+ isolate()->object_store()->set_symbol_table(saved_symbol_table_);
+ saved_symbol_table_ = Array::null();
+ }
+ new_vm_symbol_table_ = Array::null();
+ scripts_ = Array::null();
+}
+
+
+intptr_t FullSnapshotWriter::WriteVmIsolateSnapshot() {
+ NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
+ Timeline::GetIsolateStream(), "WriteVmIsolateSnapshot"));
+
+ ASSERT(vm_isolate_snapshot_buffer_ != NULL);
+ Serializer serializer(thread(),
+ kind_,
+ vm_isolate_snapshot_buffer_,
+ alloc_,
+ kInitialSize,
+ instructions_writer_);
+
+ serializer.ReserveHeader();
+ serializer.WriteVersionAndFeatures();
+ /*
+ * Now Write out the following
+ * - the symbol table
+ * - all the scripts and token streams for these scripts
+ * - the stub code (precompiled snapshots only)
+ **/
+ intptr_t num_objects = serializer.WriteVMSnapshot(new_vm_symbol_table_,
+ scripts_);
+ serializer.FillHeader(serializer.kind());
+
+ vm_isolate_snapshot_size_ = serializer.bytes_written();
+ return num_objects;
+}
+
+
+void FullSnapshotWriter::WriteIsolateFullSnapshot(
+ intptr_t num_base_objects) {
+ NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
+ Timeline::GetIsolateStream(), "WriteIsolateFullSnapshot"));
+
+ Serializer serializer(thread(),
+ kind_,
+ isolate_snapshot_buffer_,
+ alloc_,
+ kInitialSize,
+ instructions_writer_);
+ ObjectStore* object_store = isolate()->object_store();
+ ASSERT(object_store != NULL);
+
+ serializer.ReserveHeader();
+ serializer.WriteVersionAndFeatures();
+ serializer.WriteFullSnapshot(num_base_objects, object_store);
+ serializer.FillHeader(serializer.kind());
+
+ isolate_snapshot_size_ = serializer.bytes_written();
+}
+
+
+void FullSnapshotWriter::WriteFullSnapshot() {
+ intptr_t num_base_objects;
+ if (vm_isolate_snapshot_buffer() != NULL) {
+ num_base_objects = WriteVmIsolateSnapshot();
+ ASSERT(num_base_objects != 0);
+ } else {
+ num_base_objects = 0;
+ }
+
+ WriteIsolateFullSnapshot(num_base_objects);
+
+ if (Snapshot::IncludesCode(kind_)) {
+ instructions_writer_->Write();
+
+ OS::Print("VMIsolate(CodeSize): %" Pd "\n", VmIsolateSnapshotSize());
+ OS::Print("Isolate(CodeSize): %" Pd "\n", IsolateSnapshotSize());
+ OS::Print("Instructions(CodeSize): %" Pd "\n",
+ instructions_writer_->binary_size());
+ intptr_t total = VmIsolateSnapshotSize() +
+ IsolateSnapshotSize() +
+ instructions_writer_->binary_size();
+ OS::Print("Total(CodeSize): %" Pd "\n", total);
+ }
+}
+
+
+RawApiError* IsolateSnapshotReader::ReadFullSnapshot() {
+ Deserializer deserializer(thread_,
+ kind_,
+ buffer_,
+ size_,
+ instructions_buffer_,
+ data_buffer_);
+
+ RawApiError* error = deserializer.VerifyVersionAndFeatures();
+ if (error != ApiError::null()) {
+ return error;
+ }
+
+ deserializer.ReadFullSnapshot(thread_->isolate()->object_store());
+
+ return ApiError::null();
+}
+
+
+RawApiError* VmIsolateSnapshotReader::ReadVmIsolateSnapshot() {
+ Deserializer deserializer(thread_,
+ kind_,
+ buffer_,
+ size_,
+ instructions_buffer_,
+ data_buffer_);
+
+ RawApiError* error = deserializer.VerifyVersionAndFeatures();
+ if (error != ApiError::null()) {
+ return error;
+ }
+
+ deserializer.ReadVMSnapshot();
+
+ Dart::set_instructions_snapshot_buffer(instructions_buffer_);
+ Dart::set_data_snapshot_buffer(data_buffer_);
+
+ return ApiError::null();
+}
+
+} // namespace dart
« no previous file with comments | « runtime/vm/clustered_snapshot.h ('k') | runtime/vm/dart.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698