// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/snapshot.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
#include "vm/visitor.h"

namespace dart {

#define NEW_OBJECT(type)                                                       \
  ((kind == Snapshot::kFull) ? reader->New##type() : type::New())

#define NEW_OBJECT_WITH_LEN(type, len)                                         \
  ((kind == Snapshot::kFull) ? reader->New##type(len) : type::New(len))

#define NEW_OBJECT_WITH_LEN_SPACE(type, len, kind)                             \
  ((kind == Snapshot::kFull) ?                                                 \
  reader->New##type(len) : type::New(len, HEAP_SPACE(kind)))

#define OFFSET_OF_FROM(obj)                                                    \
  obj.raw()->from() - reinterpret_cast<RawObject**>(obj.raw()->ptr())

// TODO(18854): Need to assert No GC can happen here, even though
// allocations may happen.
#define READ_OBJECT_FIELDS(object, from, to, as_reference)                     \
  intptr_t num_flds = (to) - (from);                                           \
  intptr_t from_offset = OFFSET_OF_FROM(object);                               \
  for (intptr_t i = 0; i <= num_flds; i++) {                                   \
    (*reader->PassiveObjectHandle()) =                                         \
        reader->ReadObjectImpl(as_reference, object_id, (i + from_offset));    \
    object.StorePointer(((from) + i),                                          \
                        reader->PassiveObjectHandle()->raw());                 \
  }

RawClass* Class::ReadFrom(SnapshotReader* reader,
                          intptr_t object_id,
                          intptr_t tags,
                          Snapshot::Kind kind,
                          bool as_reference) {
  ASSERT(reader != NULL);

  Class& cls = Class::ZoneHandle(reader->zone(), Class::null());
  bool is_in_fullsnapshot = reader->Read<bool>();
  if ((kind == Snapshot::kFull) ||
      (kind == Snapshot::kScript && !is_in_fullsnapshot)) {
    // Read in the base information.
    classid_t class_id = reader->ReadClassIDValue();

    // Allocate class object of specified kind.
    if (kind == Snapshot::kFull) {
      cls = reader->NewClass(class_id);
    } else {
      if (class_id < kNumPredefinedCids) {
        ASSERT((class_id >= kInstanceCid) && (class_id <= kMirrorReferenceCid));
        cls = reader->isolate()->class_table()->At(class_id);
      } else {
        cls = New<Instance>(kIllegalCid);
      }
    }
    reader->AddBackRef(object_id, &cls, kIsDeserialized);

    // Set all non object fields.
    if (!RawObject::IsInternalVMdefinedClassId(class_id)) {
      // Instance size of a VM defined class is already set up.
      cls.set_instance_size_in_words(reader->Read<int32_t>());
      cls.set_next_field_offset_in_words(reader->Read<int32_t>());
    }
    cls.set_type_arguments_field_offset_in_words(reader->Read<int32_t>());
    cls.set_num_type_arguments(reader->Read<int16_t>());
    cls.set_num_own_type_arguments(reader->Read<int16_t>());
    cls.set_num_native_fields(reader->Read<uint16_t>());
    cls.set_token_pos(TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
    cls.set_state_bits(reader->Read<uint16_t>());

    // Set all the object fields.
    READ_OBJECT_FIELDS(cls, cls.raw()->from(), cls.raw()->to(), kAsReference);
    ASSERT(!cls.IsInFullSnapshot() || (kind == Snapshot::kFull));
  } else {
    cls ^= reader->ReadClassId(object_id);
    ASSERT((kind == Snapshot::kMessage) || cls.IsInFullSnapshot());
  }
  return cls.raw();
}


void RawClass::WriteTo(SnapshotWriter* writer,
                       intptr_t object_id,
                       Snapshot::Kind kind,
                       bool as_reference) {
  ASSERT(writer != NULL);
  bool is_in_fullsnapshot = Class::IsInFullSnapshot(this);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kClassCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the boolean is_in_fullsnapshot first as this will
  // help the reader decide how the rest of the information needs
  // to be interpreted.
  writer->Write<bool>(is_in_fullsnapshot);

  if ((kind == Snapshot::kFull) ||
      (kind == Snapshot::kScript && !is_in_fullsnapshot)) {
    // Write out all the non object pointer fields.
    // NOTE: cpp_vtable_ is not written.
    classid_t class_id = ptr()->id_;
    ASSERT(class_id != kIllegalCid);
    writer->Write<classid_t>(class_id);
    if (!RawObject::IsInternalVMdefinedClassId(class_id)) {
      // We don't write the instance size of VM defined classes as they
      // are already setup during initialization as part of pre populating
      // the class table.
      writer->Write<int32_t>(ptr()->instance_size_in_words_);
      writer->Write<int32_t>(ptr()->next_field_offset_in_words_);
    }
    writer->Write<int32_t>(ptr()->type_arguments_field_offset_in_words_);
    writer->Write<uint16_t>(ptr()->num_type_arguments_);
    writer->Write<uint16_t>(ptr()->num_own_type_arguments_);
    writer->Write<uint16_t>(ptr()->num_native_fields_);
    writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
    writer->Write<uint16_t>(ptr()->state_bits_);

    // Write out all the object pointer fields.
    SnapshotWriterVisitor visitor(writer, kAsReference);
    visitor.VisitPointers(from(), to());
  } else {
    if (writer->can_send_any_object() ||
        writer->AllowObjectsInDartLibrary(ptr()->library_)) {
      writer->WriteClassId(this);
    } else {
      // We do not allow regular dart instances in isolate messages.
      writer->SetWriteException(Exceptions::kArgument,
                                "Illegal argument in isolate message"
                                " : (object is a regular Dart Instance)");
    }
  }
}


RawUnresolvedClass* UnresolvedClass::ReadFrom(SnapshotReader* reader,
                                              intptr_t object_id,
                                              intptr_t tags,
                                              Snapshot::Kind kind,
                                              bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate unresolved class object.
  UnresolvedClass& unresolved_class = UnresolvedClass::ZoneHandle(
      reader->zone(), NEW_OBJECT(UnresolvedClass));
  reader->AddBackRef(object_id, &unresolved_class, kIsDeserialized);

  // Set all non object fields.
  unresolved_class.set_token_pos(
      TokenPosition::SnapshotDecode(reader->Read<int32_t>()));

  // Set all the object fields.
  READ_OBJECT_FIELDS(unresolved_class,
                     unresolved_class.raw()->from(),
                     unresolved_class.raw()->to(),
                     kAsReference);

  return unresolved_class.raw();
}


void RawUnresolvedClass::WriteTo(SnapshotWriter* writer,
                                 intptr_t object_id,
                                 Snapshot::Kind kind,
                                 bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kUnresolvedClassCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the non object pointer fields.
  writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawAbstractType* AbstractType::ReadFrom(SnapshotReader* reader,
                                        intptr_t object_id,
                                        intptr_t tags,
                                        Snapshot::Kind kind,
                                        bool as_reference) {
  UNREACHABLE();  // AbstractType is an abstract class.
  return NULL;
}


void RawAbstractType::WriteTo(SnapshotWriter* writer,
                              intptr_t object_id,
                              Snapshot::Kind kind,
                              bool as_reference) {
  UNREACHABLE();  // AbstractType is an abstract class.
}


RawType* Type::ReadFrom(SnapshotReader* reader,
                        intptr_t object_id,
                        intptr_t tags,
                        Snapshot::Kind kind,
                        bool as_reference) {
  ASSERT(reader != NULL);

  // Determine if the type class of this type is in the full snapshot.
  bool typeclass_is_in_fullsnapshot = reader->Read<bool>();

  // Allocate type object.
  Type& type = Type::ZoneHandle(reader->zone(), NEW_OBJECT(Type));
  bool is_canonical = RawObject::IsCanonical(tags);
  bool defer_canonicalization = is_canonical &&
      (kind != Snapshot::kFull && typeclass_is_in_fullsnapshot);
  reader->AddBackRef(object_id, &type, kIsDeserialized, defer_canonicalization);

  // Set all non object fields.
  type.set_token_pos(TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
  type.set_type_state(reader->Read<int8_t>());

  // Set all the object fields.
  READ_OBJECT_FIELDS(type, type.raw()->from(), type.raw()->to(), kAsReference);

  // Set the canonical bit.
  if (!defer_canonicalization && is_canonical) {
    type.SetCanonical();
  }

  return type.raw();
}


void RawType::WriteTo(SnapshotWriter* writer,
                      intptr_t object_id,
                      Snapshot::Kind kind,
                      bool as_reference) {
  ASSERT(writer != NULL);

  // Only resolved and finalized types should be written to a snapshot.
  ASSERT((ptr()->type_state_ == RawType::kFinalizedInstantiated) ||
         (ptr()->type_state_ == RawType::kFinalizedUninstantiated));
  ASSERT(ptr()->type_class_ != Object::null());

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kTypeCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out typeclass_is_in_fullsnapshot first as this will
  // help the reader decide on how to canonicalize the type object.
  intptr_t tags = writer->GetObjectTags(ptr()->type_class_);
  bool typeclass_is_in_fullsnapshot =
      (ClassIdTag::decode(tags) == kClassCid) &&
      Class::IsInFullSnapshot(reinterpret_cast<RawClass*>(ptr()->type_class_));
  writer->Write<bool>(typeclass_is_in_fullsnapshot);

  // Write out all the non object pointer fields.
  writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
  writer->Write<int8_t>(ptr()->type_state_);

  // Write out all the object pointer fields.
  ASSERT(ptr()->type_class_ != Object::null());
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawTypeRef* TypeRef::ReadFrom(SnapshotReader* reader,
                              intptr_t object_id,
                              intptr_t tags,
                              Snapshot::Kind kind,
                              bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate type ref object.
  TypeRef& type_ref = TypeRef::ZoneHandle(
      reader->zone(), NEW_OBJECT(TypeRef));
  reader->AddBackRef(object_id, &type_ref, kIsDeserialized);

  // Set all the object fields.
  READ_OBJECT_FIELDS(type_ref,
                     type_ref.raw()->from(), type_ref.raw()->to(),
                     kAsReference);

  return type_ref.raw();
}


void RawTypeRef::WriteTo(SnapshotWriter* writer,
                         intptr_t object_id,
                         Snapshot::Kind kind,
                         bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kTypeRefCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawTypeParameter* TypeParameter::ReadFrom(SnapshotReader* reader,
                                          intptr_t object_id,
                                          intptr_t tags,
                                          Snapshot::Kind kind,
                                          bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate type parameter object.
  TypeParameter& type_parameter = TypeParameter::ZoneHandle(
      reader->zone(), NEW_OBJECT(TypeParameter));
  reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);

  // Set all non object fields.
  type_parameter.set_token_pos(
      TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
  type_parameter.set_index(reader->Read<int16_t>());
  type_parameter.set_type_state(reader->Read<int8_t>());

  // Set all the object fields.
  READ_OBJECT_FIELDS(type_parameter,
                     type_parameter.raw()->from(), type_parameter.raw()->to(),
                     kAsReference);

  return type_parameter.raw();
}


void RawTypeParameter::WriteTo(SnapshotWriter* writer,
                               intptr_t object_id,
                               Snapshot::Kind kind,
                               bool as_reference) {
  ASSERT(writer != NULL);

  // Only finalized type parameters should be written to a snapshot.
  ASSERT(ptr()->type_state_ == RawTypeParameter::kFinalizedUninstantiated);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kTypeParameterCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the non object pointer fields.
  writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
  writer->Write<int16_t>(ptr()->index_);
  writer->Write<int8_t>(ptr()->type_state_);

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawBoundedType* BoundedType::ReadFrom(SnapshotReader* reader,
                                      intptr_t object_id,
                                      intptr_t tags,
                                      Snapshot::Kind kind,
                                      bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate bounded type object.
  BoundedType& bounded_type = BoundedType::ZoneHandle(
      reader->zone(), NEW_OBJECT(BoundedType));
  reader->AddBackRef(object_id, &bounded_type, kIsDeserialized);

  // Set all the object fields.
  READ_OBJECT_FIELDS(bounded_type,
                     bounded_type.raw()->from(), bounded_type.raw()->to(),
                     kAsReference);

  return bounded_type.raw();
}


void RawBoundedType::WriteTo(SnapshotWriter* writer,
                             intptr_t object_id,
                             Snapshot::Kind kind,
                             bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kBoundedTypeCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawMixinAppType* MixinAppType::ReadFrom(SnapshotReader* reader,
                                        intptr_t object_id,
                                        intptr_t tags,
                                        Snapshot::Kind kind,
                                        bool as_reference) {
  UNREACHABLE();  // MixinAppType objects do not survive finalization.
  return MixinAppType::null();
}


void RawMixinAppType::WriteTo(SnapshotWriter* writer,
                              intptr_t object_id,
                              Snapshot::Kind kind,
                              bool as_reference) {
  UNREACHABLE();  // MixinAppType objects do not survive finalization.
}


RawTypeArguments* TypeArguments::ReadFrom(SnapshotReader* reader,
                                          intptr_t object_id,
                                          intptr_t tags,
                                          Snapshot::Kind kind,
                                          bool as_reference) {
  ASSERT(reader != NULL);

  // Read the length so that we can determine instance size to allocate.
  intptr_t len = reader->ReadSmiValue();

  TypeArguments& type_arguments = TypeArguments::ZoneHandle(
      reader->zone(), NEW_OBJECT_WITH_LEN_SPACE(TypeArguments, len, kind));
  bool is_canonical = RawObject::IsCanonical(tags);
  bool defer_canonicalization = is_canonical && (kind != Snapshot::kFull);
  reader->AddBackRef(object_id,
                     &type_arguments,
                     kIsDeserialized,
                     defer_canonicalization);

  // Set the instantiations field, which is only read from a full snapshot.
  if (kind == Snapshot::kFull) {
    *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
    type_arguments.set_instantiations(*(reader->ArrayHandle()));
  } else {
    type_arguments.set_instantiations(Object::zero_array());
  }

  // Now set all the type fields.
  intptr_t offset = type_arguments.TypeAddr(0) -
      reinterpret_cast<RawAbstractType**>(type_arguments.raw()->ptr());
  for (intptr_t i = 0; i < len; i++) {
    *reader->TypeHandle() ^=
        reader->ReadObjectImpl(kAsReference, object_id, (i + offset));
    type_arguments.SetTypeAt(i, *reader->TypeHandle());
  }

  // Set the canonical bit.
  if (!defer_canonicalization && is_canonical) {
    type_arguments.SetCanonical();
  }

  return type_arguments.raw();
}


void RawTypeArguments::WriteTo(SnapshotWriter* writer,
                               intptr_t object_id,
                               Snapshot::Kind kind,
                               bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kTypeArgumentsCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the length field.
  writer->Write<RawObject*>(ptr()->length_);

  // Write out the instantiations field, but only in a full snapshot.
  if (kind == Snapshot::kFull) {
    writer->WriteObjectImpl(ptr()->instantiations_, kAsInlinedObject);
  }

  // Write out the individual types.
  intptr_t len = Smi::Value(ptr()->length_);
  for (intptr_t i = 0; i < len; i++) {
    writer->WriteObjectImpl(ptr()->types()[i], kAsReference);
  }
}


RawPatchClass* PatchClass::ReadFrom(SnapshotReader* reader,
                                    intptr_t object_id,
                                    intptr_t tags,
                                    Snapshot::Kind kind,
                                    bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate function object.
  PatchClass& cls = PatchClass::ZoneHandle(reader->zone(),
                                            NEW_OBJECT(PatchClass));
  reader->AddBackRef(object_id, &cls, kIsDeserialized);

  // Set all the object fields.
  READ_OBJECT_FIELDS(cls, cls.raw()->from(), cls.raw()->to(), kAsReference);

  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));
  return cls.raw();
}


void RawPatchClass::WriteTo(SnapshotWriter* writer,
                            intptr_t object_id,
                            Snapshot::Kind kind,
                            bool as_reference) {
  ASSERT(writer != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kPatchClassCid);
  writer->WriteTags(writer->GetObjectTags(this));
  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawClosure* Closure::ReadFrom(SnapshotReader* reader,
                              intptr_t object_id,
                              intptr_t tags,
                              Snapshot::Kind kind,
                              bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT(kind == Snapshot::kFull);

  // Allocate closure object.
  Closure& closure = Closure::ZoneHandle(
      reader->zone(), NEW_OBJECT(Closure));
  reader->AddBackRef(object_id, &closure, kIsDeserialized);

  // Set all the object fields.
  READ_OBJECT_FIELDS(closure,
                     closure.raw()->from(), closure.raw()->to(),
                     kAsReference);

  // Set the canonical bit.
  if (RawObject::IsCanonical(tags)) {
    closure.SetCanonical();
  }
  return closure.raw();
}


void RawClosure::WriteTo(SnapshotWriter* writer,
                         intptr_t object_id,
                         Snapshot::Kind kind,
                         bool as_reference) {
  ASSERT(writer != NULL);
  if ((kind == Snapshot::kMessage) || (kind == Snapshot::kScript)) {
    // Check if closure is serializable, throw an exception otherwise.
    RawFunction* func = writer->IsSerializableClosure(this);
    if (func != Function::null()) {
      writer->WriteStaticImplicitClosure(object_id,
                                         func,
                                         writer->GetObjectTags(this));
      return;
    }
  }

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kClosureCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawClosureData* ClosureData::ReadFrom(SnapshotReader* reader,
                                      intptr_t object_id,
                                      intptr_t tags,
                                      Snapshot::Kind kind,
                                      bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Allocate closure data object.
  ClosureData& data = ClosureData::ZoneHandle(
      reader->zone(), NEW_OBJECT(ClosureData));
  reader->AddBackRef(object_id, &data, kIsDeserialized);

  // Set all the object fields.
  READ_OBJECT_FIELDS(data,
                     data.raw()->from(), data.raw()->to(),
                     kAsInlinedObject);

  return data.raw();
}


void RawClosureData::WriteTo(SnapshotWriter* writer,
                             intptr_t object_id,
                             Snapshot::Kind kind,
                             bool as_reference) {
  ASSERT(writer != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kClosureDataCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Context scope.
  if (ptr()->context_scope_ == Object::empty_context_scope().raw()) {
    writer->WriteVMIsolateObject(kEmptyContextScopeObject);
  } else {
    if (ptr()->context_scope_->ptr()->is_implicit_) {
      writer->WriteObjectImpl(ptr()->context_scope_, kAsInlinedObject);
    } else {
      // We don't write non implicit context scopes in the snapshot.
      writer->WriteVMIsolateObject(kNullObject);
    }
  }

  // Parent function.
  writer->WriteObjectImpl(ptr()->parent_function_, kAsInlinedObject);

  // Signature type.
  writer->WriteObjectImpl(ptr()->signature_type_, kAsInlinedObject);

  // Canonical static closure.
  writer->WriteObjectImpl(ptr()->closure_, kAsInlinedObject);
}


RawRedirectionData* RedirectionData::ReadFrom(SnapshotReader* reader,
                                              intptr_t object_id,
                                              intptr_t tags,
                                              Snapshot::Kind kind,
                                              bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Allocate redirection data object.
  RedirectionData& data = RedirectionData::ZoneHandle(
      reader->zone(), NEW_OBJECT(RedirectionData));
  reader->AddBackRef(object_id, &data, kIsDeserialized);

  // Set all the object fields.
  READ_OBJECT_FIELDS(data,
                     data.raw()->from(), data.raw()->to(),
                     kAsReference);

  return data.raw();
}


void RawRedirectionData::WriteTo(SnapshotWriter* writer,
                                 intptr_t object_id,
                                 Snapshot::Kind kind,
                                 bool as_reference) {
  ASSERT(writer != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kRedirectionDataCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawFunction* Function::ReadFrom(SnapshotReader* reader,
                                intptr_t object_id,
                                intptr_t tags,
                                Snapshot::Kind kind,
                                bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  bool is_in_fullsnapshot = reader->Read<bool>();
  if ((kind == Snapshot::kFull) || !is_in_fullsnapshot) {
    // Allocate function object.
    Function& func = Function::ZoneHandle(
        reader->zone(), NEW_OBJECT(Function));
    reader->AddBackRef(object_id, &func, kIsDeserialized);

    // Set all the non object fields. Read the token positions now but
    // don't set them until after setting the kind.
    const int32_t token_pos = reader->Read<int32_t>();
    const int32_t end_token_pos = reader->Read<uint32_t>();
    func.set_num_fixed_parameters(reader->Read<int16_t>());
    func.set_num_optional_parameters(reader->Read<int16_t>());
    func.set_kind_tag(reader->Read<uint32_t>());
    func.set_token_pos(TokenPosition::SnapshotDecode(token_pos));
    func.set_end_token_pos(TokenPosition::SnapshotDecode(end_token_pos));
    if (reader->snapshot_code()) {
      func.set_usage_counter(0);
      func.set_deoptimization_counter(0);
      func.set_optimized_instruction_count(0);
      func.set_optimized_call_site_count(0);
    } else {
      func.set_usage_counter(reader->Read<int32_t>());
      func.set_deoptimization_counter(reader->Read<int16_t>());
      func.set_optimized_instruction_count(reader->Read<uint16_t>());
      func.set_optimized_call_site_count(reader->Read<uint16_t>());
    }

    // Set all the object fields.
    READ_OBJECT_FIELDS(func,
                       func.raw()->from(), func.raw()->to_snapshot(),
                       kAsReference);
    // Initialize all fields that are not part of the snapshot.
    if (reader->snapshot_code()) {
      func.ClearICDataArray();
      func.ClearCode();
      // Read the code object and fixup entry point.
      (*reader->CodeHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
      func.SetInstructions(*reader->CodeHandle());
    } else {
      bool is_optimized = func.usage_counter() != 0;
      if (is_optimized) {
        // Read the ic data array as the function is an optimized one.
        (*reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsReference);
        func.set_ic_data_array(*reader->ArrayHandle());
      } else {
        func.ClearICDataArray();
      }
      func.ClearCode();
    }
    return func.raw();
  } else {
    return reader->ReadFunctionId(object_id);
  }
}


void RawFunction::WriteTo(SnapshotWriter* writer,
                          intptr_t object_id,
                          Snapshot::Kind kind,
                          bool as_reference) {
  ASSERT(writer != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));
  bool is_in_fullsnapshot = false;
  bool owner_is_class = false;
  if ((kind == Snapshot::kScript) && !Function::IsSignatureFunction(this)) {
    intptr_t tags = writer->GetObjectTags(ptr()->owner_);
    intptr_t cid = ClassIdTag::decode(tags);
    owner_is_class = (cid == kClassCid);
    is_in_fullsnapshot =  owner_is_class ?
        Class::IsInFullSnapshot(reinterpret_cast<RawClass*>(ptr()->owner_)) :
        PatchClass::IsInFullSnapshot(
            reinterpret_cast<RawPatchClass*>(ptr()->owner_));
  }

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kFunctionCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the boolean is_in_fullsnapshot first as this will
  // help the reader decide how the rest of the information needs
  // to be interpreted.
  writer->Write<bool>(is_in_fullsnapshot);

  if (kind == Snapshot::kFull || !is_in_fullsnapshot) {
    bool is_optimized = Code::IsOptimized(ptr()->code_);

    // Write out all the non object fields.
    writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
    writer->Write<int32_t>(ptr()->end_token_pos_.SnapshotEncode());
    writer->Write<int16_t>(ptr()->num_fixed_parameters_);
    writer->Write<int16_t>(ptr()->num_optional_parameters_);
    writer->Write<uint32_t>(ptr()->kind_tag_);
    if (writer->snapshot_code()) {
      // Omit fields used to support de/reoptimization.
    } else {
      if (is_optimized) {
        writer->Write<int32_t>(FLAG_optimization_counter_threshold);
      } else {
        writer->Write<int32_t>(0);
      }
      writer->Write<int16_t>(ptr()->deoptimization_counter_);
      writer->Write<uint16_t>(ptr()->optimized_instruction_count_);
      writer->Write<uint16_t>(ptr()->optimized_call_site_count_);
    }

    // Write out all the object pointer fields.
    SnapshotWriterVisitor visitor(writer, kAsReference);
    visitor.VisitPointers(from(), to_snapshot());
    if (writer->snapshot_code()) {
      ASSERT(ptr()->ic_data_array_ == Array::null());
      ASSERT((ptr()->code_ == ptr()->unoptimized_code_) ||
             (ptr()->unoptimized_code_ == Code::null()));
      // Write out the code object as we are generating a precompiled snapshot.
      writer->WriteObjectImpl(ptr()->code_, kAsInlinedObject);
    } else if (is_optimized) {
      // Write out the ic data array as the function is optimized or
      // we are generating a precompiled snapshot.
      writer->WriteObjectImpl(ptr()->ic_data_array_, kAsReference);
    }
  } else {
    writer->WriteFunctionId(this, owner_is_class);
  }
}


RawField* Field::ReadFrom(SnapshotReader* reader,
                          intptr_t object_id,
                          intptr_t tags,
                          Snapshot::Kind kind,
                          bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Allocate field object.
  Field& field = Field::ZoneHandle(reader->zone(), NEW_OBJECT(Field));
  reader->AddBackRef(object_id, &field, kIsDeserialized);

  // Set all non object fields.
  if (reader->snapshot_code()) {
    field.set_token_pos(TokenPosition::kNoSource);
    ASSERT(!FLAG_use_field_guards);
  } else {
    field.set_token_pos(
        TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
    field.set_guarded_cid(reader->Read<int32_t>());
    field.set_is_nullable(reader->Read<int32_t>());
  }
  field.set_kind_bits(reader->Read<uint8_t>());

  // Set all the object fields.
  RawObject** toobj = reader->snapshot_code()
      ? field.raw()->to_precompiled_snapshot()
      : field.raw()->to();
  READ_OBJECT_FIELDS(field,
                     field.raw()->from(), toobj,
                     kAsReference);

  if (!FLAG_use_field_guards) {
    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 {
    field.InitializeGuardedListLengthInObjectOffset();
  }

  return field.raw();
}


void RawField::WriteTo(SnapshotWriter* writer,
                       intptr_t object_id,
                       Snapshot::Kind kind,
                       bool as_reference) {
  ASSERT(writer != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kFieldCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the non object fields.
  if (!writer->snapshot_code()) {
    writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
    writer->Write<int32_t>(ptr()->guarded_cid_);
    writer->Write<int32_t>(ptr()->is_nullable_);
  }
  writer->Write<uint8_t>(ptr()->kind_bits_);

  // Write out the name.
  writer->WriteObjectImpl(ptr()->name_, kAsReference);
  // Write out the owner.
  writer->WriteObjectImpl(ptr()->owner_, kAsReference);
  // Write out the type.
  writer->WriteObjectImpl(ptr()->type_, kAsReference);
  // Write out the initial static value or field offset.
  if (Field::StaticBit::decode(ptr()->kind_bits_)) {
    if (writer->snapshot_code()) {
      // For precompiled static fields, the value was already reset and
      // initializer_ now contains a Function.
      writer->WriteObjectImpl(ptr()->value_.static_value_, kAsReference);
    } else {
      // Otherwise, for static fields we write out the initial static value.
      writer->WriteObjectImpl(ptr()->initializer_.saved_value_, kAsReference);
    }
  } else {
    writer->WriteObjectImpl(ptr()->value_.offset_, kAsReference);
  }
  // Write out the initializer function or saved initial value.
  if (writer->snapshot_code()) {
    writer->WriteObjectImpl(ptr()->initializer_.precompiled_, kAsReference);
  } else {
    writer->WriteObjectImpl(ptr()->initializer_.saved_value_, kAsReference);
  }
  if (!writer->snapshot_code()) {
    // Write out the dependent code.
    writer->WriteObjectImpl(ptr()->dependent_code_, kAsReference);
    // Write out the guarded list length.
    writer->WriteObjectImpl(ptr()->guarded_list_length_, kAsReference);
  }
}


RawLiteralToken* LiteralToken::ReadFrom(SnapshotReader* reader,
                                        intptr_t object_id,
                                        intptr_t tags,
                                        Snapshot::Kind kind,
                                        bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT(kind != Snapshot::kMessage);

  // Create the literal token object.
  LiteralToken& literal_token = LiteralToken::ZoneHandle(
      reader->zone(), NEW_OBJECT(LiteralToken));
  reader->AddBackRef(object_id, &literal_token, kIsDeserialized);

  // Read the token attributes.
  Token::Kind token_kind = static_cast<Token::Kind>(reader->Read<int32_t>());
  literal_token.set_kind(token_kind);

  // Set all the object fields.
  READ_OBJECT_FIELDS(literal_token,
                     literal_token.raw()->from(), literal_token.raw()->to(),
                     kAsReference);

  return literal_token.raw();
}


void RawLiteralToken::WriteTo(SnapshotWriter* writer,
                              intptr_t object_id,
                              Snapshot::Kind kind,
                              bool as_reference) {
  ASSERT(writer != NULL);
  ASSERT(kind != Snapshot::kMessage);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kLiteralTokenCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the kind field.
  writer->Write<int32_t>(ptr()->kind_);

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawTokenStream* TokenStream::ReadFrom(SnapshotReader* reader,
                                      intptr_t object_id,
                                      intptr_t tags,
                                      Snapshot::Kind kind,
                                      bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Read the length so that we can determine number of tokens to read.
  intptr_t len = reader->ReadSmiValue();

  // Create the token stream object.
  TokenStream& token_stream = TokenStream::ZoneHandle(
      reader->zone(), NEW_OBJECT_WITH_LEN(TokenStream, len));
  reader->AddBackRef(object_id, &token_stream, kIsDeserialized);

  // Read the stream of tokens into the TokenStream object for script
  // snapshots as we made a copy of token stream.
  if (kind == Snapshot::kScript) {
    NoSafepointScope no_safepoint;
    RawExternalTypedData* stream = token_stream.GetStream();
    reader->ReadBytes(stream->ptr()->data_, len);
  }

  // Read in the literal/identifier token array.
  *(reader->TokensHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
  token_stream.SetTokenObjects(*(reader->TokensHandle()));
  // Read in the private key in use by the token stream.
  *(reader->StringHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
  token_stream.SetPrivateKey(*(reader->StringHandle()));

  return token_stream.raw();
}


void RawTokenStream::WriteTo(SnapshotWriter* writer,
                             intptr_t object_id,
                             Snapshot::Kind kind,
                             bool as_reference) {
  ASSERT(writer != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kTokenStreamCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the length field and the token stream.
  RawExternalTypedData* stream = ptr()->stream_;
  intptr_t len = Smi::Value(stream->ptr()->length_);
  writer->Write<RawObject*>(stream->ptr()->length_);
  writer->WriteBytes(stream->ptr()->data_, len);

  // Write out the literal/identifier token array.
  writer->WriteObjectImpl(ptr()->token_objects_, kAsInlinedObject);
  // Write out the private key in use by the token stream.
  writer->WriteObjectImpl(ptr()->private_key_, kAsInlinedObject);
}


RawScript* Script::ReadFrom(SnapshotReader* reader,
                            intptr_t object_id,
                            intptr_t tags,
                            Snapshot::Kind kind,
                            bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Allocate script object.
  Script& script = Script::ZoneHandle(reader->zone(), NEW_OBJECT(Script));
  reader->AddBackRef(object_id, &script, kIsDeserialized);

  script.StoreNonPointer(&script.raw_ptr()->line_offset_,
                         reader->Read<int32_t>());
  script.StoreNonPointer(&script.raw_ptr()->col_offset_,
                         reader->Read<int32_t>());
  script.StoreNonPointer(&script.raw_ptr()->kind_,
                         reader->Read<int8_t>());

  *reader->StringHandle() ^= String::null();
  script.set_source(*reader->StringHandle());
  *reader->StreamHandle() ^= TokenStream::null();
  script.set_tokens(*reader->StreamHandle());

  // Set all the object fields.
  // TODO(5411462): Need to assert No GC can happen here, even though
  // allocations may happen.
  RawObject** toobj = reader->snapshot_code()
      ? script.raw()->to_precompiled_snapshot()
      : script.raw()->to_snapshot();
  intptr_t num_flds = (toobj - script.raw()->from());
  for (intptr_t i = 0; i <= num_flds; i++) {
    (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
    script.StorePointer((script.raw()->from() + i),
                        reader->PassiveObjectHandle()->raw());
  }

  return script.raw();
}


void RawScript::WriteTo(SnapshotWriter* writer,
                        intptr_t object_id,
                        Snapshot::Kind kind,
                        bool as_reference) {
  ASSERT(writer != NULL);
  ASSERT(tokens_ != TokenStream::null());
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kScriptCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the non object fields.
  writer->Write<int32_t>(ptr()->line_offset_);
  writer->Write<int32_t>(ptr()->col_offset_);
  writer->Write<int8_t>(ptr()->kind_);

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  RawObject** toobj = writer->snapshot_code() ? to_precompiled_snapshot()
                                              : to_snapshot();
  visitor.VisitPointers(from(), toobj);
}


RawLibrary* Library::ReadFrom(SnapshotReader* reader,
                              intptr_t object_id,
                              intptr_t tags,
                              Snapshot::Kind kind,
                              bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT(kind != Snapshot::kMessage);

  Library& library = Library::ZoneHandle(reader->zone(), Library::null());
  reader->AddBackRef(object_id, &library, kIsDeserialized);

  bool is_in_fullsnapshot = reader->Read<bool>();
  if ((kind == Snapshot::kScript) && is_in_fullsnapshot) {
    // Lookup the object as it should already exist in the heap.
    *reader->StringHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
    library = Library::LookupLibrary(*reader->StringHandle());
    ASSERT(library.is_in_fullsnapshot());
  } else {
    // Allocate library object.
    library = NEW_OBJECT(Library);

    // Set all non object fields.
    library.StoreNonPointer(&library.raw_ptr()->index_,
                            reader->ReadClassIDValue());
    library.StoreNonPointer(&library.raw_ptr()->num_imports_,
                            reader->Read<uint16_t>());
    library.StoreNonPointer(&library.raw_ptr()->load_state_,
                            reader->Read<int8_t>());
    library.StoreNonPointer(&library.raw_ptr()->corelib_imported_,
                            reader->Read<bool>());
    library.StoreNonPointer(&library.raw_ptr()->is_dart_scheme_,
                            reader->Read<bool>());
    library.StoreNonPointer(&library.raw_ptr()->debuggable_,
                            reader->Read<bool>());
    if (kind == Snapshot::kFull) {
      is_in_fullsnapshot = true;
    }
    library.StoreNonPointer(&library.raw_ptr()->is_in_fullsnapshot_,
                            is_in_fullsnapshot);
    // The native resolver and symbolizer are not serialized.
    library.set_native_entry_resolver(NULL);
    library.set_native_entry_symbol_resolver(NULL);

    // Set all the object fields.
    // TODO(5411462): Need to assert No GC can happen here, even though
    // allocations may happen.
    intptr_t num_flds = (library.raw()->to_snapshot() - library.raw()->from());
    for (intptr_t i = 0; i <= num_flds; i++) {
      (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
      library.StorePointer((library.raw()->from() + i),
                           reader->PassiveObjectHandle()->raw());
    }
    // Initialize cache of resolved names.
    const intptr_t kInitialNameCacheSize = 64;
    if (kind != Snapshot::kFull) {
      // The cache of resolved names in library scope is not serialized.
      library.InitResolvedNamesCache(kInitialNameCacheSize);
      library.Register();
    } else {
      library.InitResolvedNamesCache(kInitialNameCacheSize, reader);
    }
    // Initialize cache of loaded scripts.
    library.StorePointer(&library.raw_ptr()->loaded_scripts_, Array::null());
  }
  return library.raw();
}


void RawLibrary::WriteTo(SnapshotWriter* writer,
                         intptr_t object_id,
                         Snapshot::Kind kind,
                         bool as_reference) {
  ASSERT(writer != NULL);
  ASSERT(kind != Snapshot::kMessage);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kLibraryCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the boolean is_in_fullsnapshot_ first as this will
  // help the reader decide how the rest of the information needs
  // to be interpreted.
  writer->Write<bool>(ptr()->is_in_fullsnapshot_);

  if ((kind == Snapshot::kScript) && ptr()->is_in_fullsnapshot_) {
    // Write out library URL so that it can be looked up when reading.
    writer->WriteObjectImpl(ptr()->url_, kAsInlinedObject);
  } else {
    ASSERT((kind == Snapshot::kFull) || !ptr()->is_in_fullsnapshot_);
    // Write out all non object fields.
    ASSERT(ptr()->index_ != static_cast<classid_t>(-1));
    writer->WriteClassIDValue(ptr()->index_);
    writer->Write<uint16_t>(ptr()->num_imports_);
    writer->Write<int8_t>(ptr()->load_state_);
    writer->Write<bool>(ptr()->corelib_imported_);
    writer->Write<bool>(ptr()->is_dart_scheme_);
    writer->Write<bool>(ptr()->debuggable_);
    // We do not serialize the native resolver or symbolizer. These need to be
    // explicitly set after deserialization.

    // We do not write the loaded_scripts_ and resolved_names_ caches to the
    // snapshot. They get initialized when reading the library from the
    // snapshot and will be rebuilt lazily.
    // Write out all the object pointer fields.
    SnapshotWriterVisitor visitor(writer, kAsReference);
    visitor.VisitPointers(from(), to_snapshot());
  }
}


RawLibraryPrefix* LibraryPrefix::ReadFrom(SnapshotReader* reader,
                                          intptr_t object_id,
                                          intptr_t tags,
                                          Snapshot::Kind kind,
                                          bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Allocate library prefix object.
  LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(
      reader->zone(), NEW_OBJECT(LibraryPrefix));
  reader->AddBackRef(object_id, &prefix, kIsDeserialized);

  // Set all non object fields.
  prefix.StoreNonPointer(&prefix.raw_ptr()->num_imports_,
                         reader->Read<int16_t>());
  prefix.StoreNonPointer(&prefix.raw_ptr()->is_deferred_load_,
                         reader->Read<bool>());
  prefix.StoreNonPointer(&prefix.raw_ptr()->is_loaded_, reader->Read<bool>());

  // Set all the object fields.
  RawObject** toobj = reader->snapshot_code()
      ? prefix.raw()->to_precompiled_snapshot()
      : prefix.raw()->to();
  READ_OBJECT_FIELDS(prefix,
                     prefix.raw()->from(), toobj,
                     kAsReference);
  if (reader->snapshot_code()) {
    prefix.StorePointer(&prefix.raw_ptr()->imports_,
                        Array::null());
    prefix.StorePointer(&prefix.raw_ptr()->dependent_code_,
                        Array::null());
  }

  return prefix.raw();
}


void RawLibraryPrefix::WriteTo(SnapshotWriter* writer,
                               intptr_t object_id,
                               Snapshot::Kind kind,
                               bool as_reference) {
  ASSERT(writer != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kLibraryPrefixCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all non object fields.
  writer->Write<int16_t>(ptr()->num_imports_);
  writer->Write<bool>(ptr()->is_deferred_load_);
  writer->Write<bool>(ptr()->is_loaded_);

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  RawObject** toobj = writer->snapshot_code() ? to_precompiled_snapshot()
                                              : to();
  visitor.VisitPointers(from(), toobj);
}


RawNamespace* Namespace::ReadFrom(SnapshotReader* reader,
                                  intptr_t object_id,
                                  intptr_t tags,
                                  Snapshot::Kind kind,
                                  bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Allocate Namespace object.
  Namespace& ns = Namespace::ZoneHandle(
      reader->zone(), NEW_OBJECT(Namespace));
  reader->AddBackRef(object_id, &ns, kIsDeserialized);

  // Set all the object fields.
  READ_OBJECT_FIELDS(ns, ns.raw()->from(), ns.raw()->to(), kAsReference);

  return ns.raw();
}


void RawNamespace::WriteTo(SnapshotWriter* writer,
                           intptr_t object_id,
                           Snapshot::Kind kind,
                           bool as_reference) {
  ASSERT(writer != NULL);
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kNamespaceCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


#if defined(DEBUG)
static uword Checksum(uword entry, intptr_t size) {
  uword sum = 0;
  uword* start = reinterpret_cast<uword*>(entry);
  uword* end = reinterpret_cast<uword*>(entry + size);
  for (uword* cursor = start; cursor < end; cursor++) {
    sum ^= *cursor;
  }
  return sum;
}
#endif


RawCode* Code::ReadFrom(SnapshotReader* reader,
                        intptr_t object_id,
                        intptr_t tags,
                        Snapshot::Kind kind,
                        bool as_reference) {
  ASSERT(reader->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  Code& result = Code::ZoneHandle(reader->zone(), NEW_OBJECT_WITH_LEN(Code, 0));
  reader->AddBackRef(object_id, &result, kIsDeserialized);

  result.set_compile_timestamp(0);
  result.set_state_bits(reader->Read<int32_t>());
  result.set_lazy_deopt_pc_offset(-1);

  int32_t text_offset = reader->Read<int32_t>();
  int32_t instructions_size = reader->Read<int32_t>();
  uword entry_point = reader->GetInstructionsAt(text_offset);

#if defined(DEBUG)
  uword expected_check = reader->Read<uword>();
  uword actual_check = Checksum(entry_point, instructions_size);
  ASSERT(expected_check == actual_check);
#endif

  result.StoreNonPointer(&result.raw_ptr()->entry_point_, entry_point);

  result.StorePointer(reinterpret_cast<RawSmi*const*>(
                          &result.raw_ptr()->instructions_),
                      Smi::New(instructions_size));

  (*reader->PassiveObjectHandle()) ^= reader->ReadObjectImpl(kAsReference);
  result.StorePointer(reinterpret_cast<RawObject*const*>(
                          &result.raw_ptr()->object_pool_),
                      reader->PassiveObjectHandle()->raw());

  (*reader->PassiveObjectHandle()) ^= reader->ReadObjectImpl(kAsReference);
  result.StorePointer(&result.raw_ptr()->owner_,
                      reader->PassiveObjectHandle()->raw());

  (*reader->PassiveObjectHandle()) ^= reader->ReadObjectImpl(kAsReference);
  result.StorePointer(reinterpret_cast<RawObject*const*>(
                          &result.raw_ptr()->exception_handlers_),
                      reader->PassiveObjectHandle()->raw());

  (*reader->PassiveObjectHandle()) ^= reader->ReadObjectImpl(kAsReference);
  result.StorePointer(reinterpret_cast<RawObject*const*>(
                          &result.raw_ptr()->pc_descriptors_),
                      reader->PassiveObjectHandle()->raw());

  (*reader->PassiveObjectHandle()) ^= reader->ReadObjectImpl(kAsReference);
  result.StorePointer(reinterpret_cast<RawObject*const*>(
                          &result.raw_ptr()->code_source_map_),
                      reader->PassiveObjectHandle()->raw());

  (*reader->PassiveObjectHandle()) ^= reader->ReadObjectImpl(kAsReference);
  result.StorePointer(reinterpret_cast<RawObject*const*>(
                          &result.raw_ptr()->stackmaps_),
                      reader->PassiveObjectHandle()->raw());

  result.StorePointer(&result.raw_ptr()->deopt_info_array_,
                      Array::null());
  result.StorePointer(&result.raw_ptr()->static_calls_target_table_,
                      Array::null());
  result.StorePointer(&result.raw_ptr()->var_descriptors_,
                      LocalVarDescriptors::null());
  result.StorePointer(&result.raw_ptr()->inlined_metadata_,
                      Array::null());
  result.StorePointer(&result.raw_ptr()->comments_,
                      Array::null());
  result.StorePointer(&result.raw_ptr()->return_address_metadata_,
                      Object::null());

  ASSERT(result.Size() == instructions_size);
  ASSERT(result.EntryPoint() == entry_point);

  return result.raw();
}


void RawCode::WriteTo(SnapshotWriter* writer,
                      intptr_t object_id,
                      Snapshot::Kind kind,
                      bool as_reference) {
  ASSERT(writer->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  intptr_t pointer_offsets_length =
      Code::PtrOffBits::decode(ptr()->state_bits_);
  if (pointer_offsets_length != 0) {
    // Should only be IA32.
    FATAL("Cannot serialize code with embedded pointers");
  }

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kCodeCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the non object fields.
  writer->Write<int32_t>(ptr()->state_bits_);

  RawInstructions* instr = ptr()->instructions_;
  intptr_t size = instr->ptr()->size_;
  int32_t text_offset = writer->GetInstructionsId(instr, this);
  writer->Write<int32_t>(text_offset);
  writer->Write<int32_t>(size);
#if defined(DEBUG)
  uword entry = ptr()->entry_point_;
  uword check = Checksum(entry, size);
  writer->Write<uword>(check);
#endif

  writer->WriteObjectImpl(ptr()->object_pool_, kAsReference);
  writer->WriteObjectImpl(ptr()->owner_, kAsReference);
  writer->WriteObjectImpl(ptr()->exception_handlers_, kAsReference);
  writer->WriteObjectImpl(ptr()->pc_descriptors_, kAsReference);
  writer->WriteObjectImpl(ptr()->code_source_map_, kAsReference);
  writer->WriteObjectImpl(ptr()->stackmaps_, kAsReference);
}


RawInstructions* Instructions::ReadFrom(SnapshotReader* reader,
                                        intptr_t object_id,
                                        intptr_t tags,
                                        Snapshot::Kind kind,
                                        bool as_reference) {
  UNREACHABLE();
  return Instructions::null();
}


void RawInstructions::WriteTo(SnapshotWriter* writer,
                              intptr_t object_id,
                              Snapshot::Kind kind,
                              bool as_reference) {
  UNREACHABLE();
}


RawObjectPool* ObjectPool::ReadFrom(SnapshotReader* reader,
                                    intptr_t object_id,
                                    intptr_t tags,
                                    Snapshot::Kind kind,
                                    bool as_reference) {
  ASSERT(reader->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  intptr_t len = reader->Read<intptr_t>();
  ObjectPool* result = NULL;
  DeserializeState state;
  if (!as_reference) {
    result = reinterpret_cast<ObjectPool*>(reader->GetBackRef(object_id));
    state = kIsDeserialized;
  } else {
    state = kIsNotDeserialized;
  }
  if (result == NULL) {
    result = &(ObjectPool::ZoneHandle(
        reader->zone(), NEW_OBJECT_WITH_LEN(ObjectPool, len)));
    reader->AddBackRef(object_id, result, state);
  }
  if (!as_reference) {
    // Read all the individual elements for inlined objects.
    const TypedData& info_array =
        TypedData::Handle(reader->NewTypedData(kTypedDataInt8ArrayCid, len));
    result->set_info_array(info_array);

    NoSafepointScope no_safepoint;
    for (intptr_t i = 0; i < len; i++) {
      ObjectPool::EntryType entry_type =
          static_cast<ObjectPool::EntryType>(reader->Read<int8_t>());
      *reinterpret_cast<int8_t*>(info_array.DataAddr(i)) = entry_type;
      switch (entry_type) {
        case ObjectPool::kTaggedObject: {
          (*reader->PassiveObjectHandle()) =
              reader->ReadObjectImpl(kAsReference);
          result->SetObjectAt(i, *(reader->PassiveObjectHandle()));
          break;
        }
        case ObjectPool::kImmediate: {
          intptr_t raw_value = reader->Read<intptr_t>();
          result->SetRawValueAt(i, raw_value);
          break;
        }
        case ObjectPool::kNativeEntry: {
          // Read nothing. Initialize with the lazy link entry.
          uword new_entry = NativeEntry::LinkNativeCallEntry();
          result->SetRawValueAt(i, static_cast<intptr_t>(new_entry));
          break;
        }
        default:
          UNREACHABLE();
      }
    }
  }
  return result->raw();
}


void RawObjectPool::WriteTo(SnapshotWriter* writer,
                            intptr_t object_id,
                            Snapshot::Kind kind,
                            bool as_reference) {
  ASSERT(writer->snapshot_code());
  ASSERT(kind == Snapshot::kFull);
  intptr_t tags = writer->GetObjectTags(this);
  intptr_t length = ptr()->length_;

  if (as_reference) {
    // Write out the serialization header value for this object.
    writer->WriteInlinedObjectHeader(kOmittedObjectId);

    // Write out the class information.
    writer->WriteVMIsolateObject(kObjectPoolCid);
    writer->WriteTags(tags);

    // Write out the length field.
    writer->Write<intptr_t>(length);
  } else {
    // Write out the serialization header value for this object.
    writer->WriteInlinedObjectHeader(object_id);

    // Write out the class and tags information.
    writer->WriteVMIsolateObject(kObjectPoolCid);
    writer->WriteTags(tags);

    RawTypedData* info_array = ptr()->info_array_->ptr();
    ASSERT(info_array != TypedData::null());

    writer->Write<intptr_t>(length);
    for (intptr_t i = 0; i < length; i++) {
      ObjectPool::EntryType entry_type =
          static_cast<ObjectPool::EntryType>(info_array->data()[i]);
      writer->Write<int8_t>(entry_type);
      Entry& entry = ptr()->data()[i];
      switch (entry_type) {
        case ObjectPool::kTaggedObject: {
          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.
            writer->WriteObjectImpl(
                StubCode::CallBootstrapCFunction_entry()->code(), kAsReference);
          } else {
            writer->WriteObjectImpl(entry.raw_obj_, kAsReference);
          }
          break;
        }
        case ObjectPool::kImmediate: {
          writer->Write<intptr_t>(entry.raw_value_);
          break;
        }
        case ObjectPool::kNativeEntry: {
          // Write nothing. Will initialize with the lazy link entry.
          break;
        }
        default:
          UNREACHABLE();
      }
    }
  }
}


RawPcDescriptors* PcDescriptors::ReadFrom(SnapshotReader* reader,
                                          intptr_t object_id,
                                          intptr_t tags,
                                          Snapshot::Kind kind,
                                          bool as_reference) {
  ASSERT(reader->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  intptr_t offset = reader->Read<int32_t>();
  PcDescriptors& result = PcDescriptors::ZoneHandle(reader->zone());
  result ^= reader->GetObjectAt(offset);
  reader->AddBackRef(object_id, &result, kIsDeserialized);

  return result.raw();
}


void RawPcDescriptors::WriteTo(SnapshotWriter* writer,
                               intptr_t object_id,
                               Snapshot::Kind kind,
                               bool as_reference) {
  ASSERT(writer->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);
  writer->WriteIndexedObject(kPcDescriptorsCid);
  writer->WriteTags(writer->GetObjectTags(this));

  writer->Write<int32_t>(writer->GetObjectId(this));
}


RawCodeSourceMap* CodeSourceMap::ReadFrom(SnapshotReader* reader,
                                          intptr_t object_id,
                                          intptr_t tags,
                                          Snapshot::Kind kind,
                                          bool as_reference) {
  ASSERT(reader->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  const int32_t length = reader->Read<int32_t>();
  CodeSourceMap& result =
      CodeSourceMap::ZoneHandle(reader->zone(),
                                NEW_OBJECT_WITH_LEN(CodeSourceMap, length));
  reader->AddBackRef(object_id, &result, kIsDeserialized);

  if (result.Length() > 0) {
    NoSafepointScope no_safepoint;
    intptr_t len = result.Length();
    uint8_t* data = result.UnsafeMutableNonPointer(result.raw_ptr()->data());
    reader->ReadBytes(data, len);
  }

  return result.raw();
}


void RawCodeSourceMap::WriteTo(SnapshotWriter* writer,
                               intptr_t object_id,
                               Snapshot::Kind kind,
                               bool as_reference) {
  ASSERT(writer->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);
  writer->WriteIndexedObject(kCodeSourceMapCid);
  writer->WriteTags(writer->GetObjectTags(this));
  writer->Write<int32_t>(ptr()->length_);
  if (ptr()->length_ > 0) {
    intptr_t len = ptr()->length_;
    uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
    writer->WriteBytes(data, len);
  }
}


RawStackmap* Stackmap::ReadFrom(SnapshotReader* reader,
                                intptr_t object_id,
                                intptr_t tags,
                                Snapshot::Kind kind,
                                bool as_reference) {
  ASSERT(reader->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  intptr_t offset = reader->Read<int32_t>();
  Stackmap& result = Stackmap::ZoneHandle(reader->zone());
  result ^= reader->GetObjectAt(offset);
  reader->AddBackRef(object_id, &result, kIsDeserialized);

  return result.raw();
}


void RawStackmap::WriteTo(SnapshotWriter* writer,
                          intptr_t object_id,
                          Snapshot::Kind kind,
                          bool as_reference) {
  ASSERT(writer->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);
  writer->WriteIndexedObject(kStackmapCid);
  writer->WriteTags(writer->GetObjectTags(this));

  writer->Write<int32_t>(writer->GetObjectId(this));
}


RawLocalVarDescriptors* LocalVarDescriptors::ReadFrom(SnapshotReader* reader,
                                                      intptr_t object_id,
                                                      intptr_t tags,
                                                      Snapshot::Kind kind,
                                                      bool as_reference) {
  ASSERT(reader->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  const int32_t num_entries = reader->Read<int32_t>();

  LocalVarDescriptors& result =
      LocalVarDescriptors::ZoneHandle(reader->zone(),
                                      NEW_OBJECT_WITH_LEN(LocalVarDescriptors,
                                                          num_entries));
  reader->AddBackRef(object_id, &result, kIsDeserialized);

  for (intptr_t i = 0; i < num_entries; i++) {
    (*reader->StringHandle()) ^= reader->ReadObjectImpl(kAsReference);
    result.StorePointer(result.raw()->nameAddrAt(i),
                        reader->StringHandle()->raw());
  }

  if (num_entries > 0) {
    NoSafepointScope no_safepoint;
    intptr_t len = num_entries * sizeof(RawLocalVarDescriptors::VarInfo);
    uint8_t* data = result.UnsafeMutableNonPointer(
        reinterpret_cast<const uint8_t*>(result.raw()->data()));
    reader->ReadBytes(data, len);
  }

  return result.raw();
}


void RawLocalVarDescriptors::WriteTo(SnapshotWriter* writer,
                                     intptr_t object_id,
                                     Snapshot::Kind kind,
                                     bool as_reference) {
  ASSERT(writer->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);
  writer->WriteIndexedObject(kLocalVarDescriptorsCid);
  writer->WriteTags(writer->GetObjectTags(this));
  writer->Write<int32_t>(ptr()->num_entries_);
  for (intptr_t i = 0; i < ptr()->num_entries_; i++) {
    writer->WriteObjectImpl(ptr()->names()[i], kAsReference);
  }
  if (ptr()->num_entries_ > 0) {
    intptr_t len = ptr()->num_entries_ * sizeof(VarInfo);
    uint8_t* data = reinterpret_cast<uint8_t*>(this->data());
    writer->WriteBytes(data, len);
  }
}


RawExceptionHandlers* ExceptionHandlers::ReadFrom(SnapshotReader* reader,
                                                  intptr_t object_id,
                                                  intptr_t tags,
                                                  Snapshot::Kind kind,
                                                  bool as_reference) {
  ASSERT(reader->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  const int32_t num_entries = reader->Read<int32_t>();
  ExceptionHandlers& result =
      ExceptionHandlers::ZoneHandle(reader->zone(),
                                    NEW_OBJECT_WITH_LEN(ExceptionHandlers,
                                                        num_entries));
  reader->AddBackRef(object_id, &result, kIsDeserialized);

  if (result.num_entries() > 0) {
    NoSafepointScope no_safepoint;
    const intptr_t len =
        result.num_entries() * sizeof(RawExceptionHandlers::HandlerInfo);
    uint8_t* data = result.UnsafeMutableNonPointer(
        reinterpret_cast<const uint8_t*>(result.raw_ptr()->data()));
    reader->ReadBytes(data, len);
  }

  *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
  result.StorePointer(&result.raw_ptr()->handled_types_data_,
                      reader->ArrayHandle()->raw());

  return result.raw();
}


void RawExceptionHandlers::WriteTo(SnapshotWriter* writer,
                                   intptr_t object_id,
                                   Snapshot::Kind kind,
                                   bool as_reference) {
  ASSERT(writer->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);
  writer->WriteIndexedObject(kExceptionHandlersCid);
  writer->WriteTags(writer->GetObjectTags(this));
  writer->Write<int32_t>(ptr()->num_entries_);

  if (ptr()->num_entries_ > 0) {
    intptr_t len = ptr()->num_entries_ * sizeof(HandlerInfo);
    uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
    writer->WriteBytes(data, len);
  }

  writer->WriteObjectImpl(ptr()->handled_types_data_, kAsInlinedObject);
}


RawContext* Context::ReadFrom(SnapshotReader* reader,
                              intptr_t object_id,
                              intptr_t tags,
                              Snapshot::Kind kind,
                              bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate context object.
  int32_t num_vars = reader->Read<int32_t>();
  Context& context = Context::ZoneHandle(reader->zone());
  reader->AddBackRef(object_id, &context, kIsDeserialized);
  if (num_vars == 0) {
    context ^= reader->object_store()->empty_context();
  } else {
    context ^= NEW_OBJECT_WITH_LEN(Context, num_vars);

    // Set all the object fields.
    // TODO(5411462): Need to assert No GC can happen here, even though
    // allocations may happen.
    intptr_t num_flds = (context.raw()->to(num_vars) - context.raw()->from());
    for (intptr_t i = 0; i <= num_flds; i++) {
      (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
      context.StorePointer((context.raw()->from() + i),
                           reader->PassiveObjectHandle()->raw());
    }
  }
  return context.raw();
}


void RawContext::WriteTo(SnapshotWriter* writer,
                         intptr_t object_id,
                         Snapshot::Kind kind,
                         bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kContextCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out num of variables in the context.
  int32_t num_variables = ptr()->num_variables_;
  writer->Write<int32_t>(num_variables);
  if (num_variables != 0) {
    // Write out all the object pointer fields.
    SnapshotWriterVisitor visitor(writer, kAsReference);
    visitor.VisitPointers(from(), to(num_variables));
  }
}


RawContextScope* ContextScope::ReadFrom(SnapshotReader* reader,
                                        intptr_t object_id,
                                        intptr_t tags,
                                        Snapshot::Kind kind,
                                        bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate context object.
  bool is_implicit = reader->Read<bool>();
  if (is_implicit) {
    ContextScope& context_scope = ContextScope::ZoneHandle();
    if (kind == Snapshot::kFull) {
      context_scope = reader->NewContextScope(1);
      context_scope.set_is_implicit(true);
    } else {
      context_scope = ContextScope::New(1, true);
    }
    reader->AddBackRef(object_id, &context_scope, kIsDeserialized);

    *reader->TypeHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);

    // Create a descriptor for 'this' variable.
    context_scope.SetTokenIndexAt(0, TokenPosition::kMinSource);
    context_scope.SetNameAt(0, Symbols::This());
    context_scope.SetIsFinalAt(0, true);
    context_scope.SetIsConstAt(0, false);
    context_scope.SetTypeAt(0, *reader->TypeHandle());
    context_scope.SetContextIndexAt(0, 0);
    context_scope.SetContextLevelAt(0, 0);
    return context_scope.raw();
  }
  UNREACHABLE();
  return NULL;
}


void RawContextScope::WriteTo(SnapshotWriter* writer,
                              intptr_t object_id,
                              Snapshot::Kind kind,
                              bool as_reference) {
  ASSERT(writer != NULL);

  if (ptr()->is_implicit_) {
    ASSERT(ptr()->num_variables_ == 1);
    const VariableDesc* var = ptr()->VariableDescAddr(0);

    // Write out the serialization header value for this object.
    writer->WriteInlinedObjectHeader(object_id);

    // Write out the class and tags information.
    writer->WriteVMIsolateObject(kContextScopeCid);
    writer->WriteTags(writer->GetObjectTags(this));

    // Write out is_implicit flag for the context scope.
    writer->Write<bool>(true);

    // Write out the type of 'this' the variable.
    writer->WriteObjectImpl(var->type, kAsInlinedObject);

    return;
  }
  UNREACHABLE();
}


RawICData* ICData::ReadFrom(SnapshotReader* reader,
                            intptr_t object_id,
                            intptr_t tags,
                            Snapshot::Kind kind,
                            bool as_reference) {
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  ICData& result = ICData::ZoneHandle(reader->zone(), NEW_OBJECT(ICData));
  reader->AddBackRef(object_id, &result, kIsDeserialized);

  result.set_deopt_id(reader->Read<int32_t>());
  result.set_state_bits(reader->Read<uint32_t>());

  // Set all the object fields.
  RawObject** toobj = reader->snapshot_code()
      ? result.raw()->to_precompiled_snapshot()
      : result.raw()->to();
  READ_OBJECT_FIELDS(result,
                     result.raw()->from(), toobj,
                     kAsReference);
  if (reader->snapshot_code()) {
    result.set_owner(Function::Handle(reader->zone()));
  }

  return result.raw();
}


void RawICData::WriteTo(SnapshotWriter* writer,
                        intptr_t object_id,
                        Snapshot::Kind kind,
                        bool as_reference) {
  ASSERT((kind == Snapshot::kScript) || (kind == Snapshot::kFull));

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kICDataCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the non object fields.
  writer->Write<int32_t>(ptr()->deopt_id_);
  writer->Write<uint32_t>(ptr()->state_bits_);

  // Write out all the object pointer fields.
  // In precompiled snapshots, omit the owner field. The owner field may
  // refer to a function which was always inlined and no longer needed.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  RawObject** toobj = writer->snapshot_code() ? to_precompiled_snapshot()
                                              : to();
  visitor.VisitPointers(from(), toobj);
}


RawMegamorphicCache* MegamorphicCache::ReadFrom(SnapshotReader* reader,
                                                intptr_t object_id,
                                                intptr_t tags,
                                                Snapshot::Kind kind,
                                                bool as_reference) {
  ASSERT(reader->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  MegamorphicCache& result =
      MegamorphicCache::ZoneHandle(reader->zone(),
                                   NEW_OBJECT(MegamorphicCache));
  reader->AddBackRef(object_id, &result, kIsDeserialized);

  result.set_filled_entry_count(reader->Read<int32_t>());

  // Set all the object fields.
  READ_OBJECT_FIELDS(result,
                     result.raw()->from(), result.raw()->to(),
                     kAsReference);

  return result.raw();
}


void RawMegamorphicCache::WriteTo(SnapshotWriter* writer,
                                  intptr_t object_id,
                                  Snapshot::Kind kind,
                                  bool as_reference) {
  ASSERT(writer->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kMegamorphicCacheCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the non object fields.
  writer->Write<int32_t>(ptr()->filled_entry_count_);

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawSubtypeTestCache* SubtypeTestCache::ReadFrom(SnapshotReader* reader,
                                                intptr_t object_id,
                                                intptr_t tags,
                                                Snapshot::Kind kind,
                                                bool as_reference) {
  ASSERT(reader->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  SubtypeTestCache& result =
      SubtypeTestCache::ZoneHandle(reader->zone(),
                                   NEW_OBJECT(SubtypeTestCache));
  reader->AddBackRef(object_id, &result, kIsDeserialized);

  // Set all the object fields.
  // TODO(5411462): Need to assert No GC can happen here, even though
  // allocations may happen.
  (*reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsReference);
  result.StorePointer(&result.raw_ptr()->cache_,
                      reader->ArrayHandle()->raw());

  return result.raw();
}


void RawSubtypeTestCache::WriteTo(SnapshotWriter* writer,
                                  intptr_t object_id,
                                  Snapshot::Kind kind,
                                  bool as_reference) {
  ASSERT(writer->snapshot_code());
  ASSERT(kind == Snapshot::kFull);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kSubtypeTestCacheCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the object pointer fields.
  writer->WriteObjectImpl(ptr()->cache_, kAsReference);
}


RawError* Error::ReadFrom(SnapshotReader* reader,
                          intptr_t object_id,
                          intptr_t tags,
                          Snapshot::Kind kind,
                          bool as_referenec) {
  UNREACHABLE();
  return Error::null();  // Error is an abstract class.
}


void RawError::WriteTo(SnapshotWriter* writer,
                       intptr_t object_id,
                       Snapshot::Kind kind,
                       bool as_reference) {
  UNREACHABLE();  // Error is an abstract class.
}


RawApiError* ApiError::ReadFrom(SnapshotReader* reader,
                                intptr_t object_id,
                                intptr_t tags,
                                Snapshot::Kind kind,
                                bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate ApiError object.
  ApiError& api_error =
      ApiError::ZoneHandle(reader->zone(), NEW_OBJECT(ApiError));
  reader->AddBackRef(object_id, &api_error, kIsDeserialized);

  // Set all the object fields.
  READ_OBJECT_FIELDS(api_error,
                     api_error.raw()->from(), api_error.raw()->to(),
                     kAsReference);

  return api_error.raw();
}


void RawApiError::WriteTo(SnapshotWriter* writer,
                          intptr_t object_id,
                          Snapshot::Kind kind,
                          bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kApiErrorCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawLanguageError* LanguageError::ReadFrom(SnapshotReader* reader,
                                          intptr_t object_id,
                                          intptr_t tags,
                                          Snapshot::Kind kind,
                                          bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate LanguageError object.
  LanguageError& language_error =
      LanguageError::ZoneHandle(reader->zone(), NEW_OBJECT(LanguageError));
  reader->AddBackRef(object_id, &language_error, kIsDeserialized);

  // Set all non object fields.
  language_error.set_token_pos(
      TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
  language_error.set_report_after_token(reader->Read<bool>());
  language_error.set_kind(reader->Read<uint8_t>());

  // Set all the object fields.
  READ_OBJECT_FIELDS(language_error,
                     language_error.raw()->from(), language_error.raw()->to(),
                     kAsReference);

  return language_error.raw();
}


void RawLanguageError::WriteTo(SnapshotWriter* writer,
                               intptr_t object_id,
                               Snapshot::Kind kind,
                               bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kLanguageErrorCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the non object fields.
  writer->Write<int32_t>(ptr()->token_pos_.SnapshotEncode());
  writer->Write<bool>(ptr()->report_after_token_);
  writer->Write<uint8_t>(ptr()->kind_);

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawUnhandledException* UnhandledException::ReadFrom(SnapshotReader* reader,
                                                    intptr_t object_id,
                                                    intptr_t tags,
                                                    Snapshot::Kind kind,
                                                    bool as_reference) {
  UnhandledException& result = UnhandledException::ZoneHandle(
      reader->zone(), NEW_OBJECT(UnhandledException));
  reader->AddBackRef(object_id, &result, kIsDeserialized);

  // Set all the object fields.
  READ_OBJECT_FIELDS(result,
                     result.raw()->from(), result.raw()->to(),
                     kAsReference);

  return result.raw();
}


void RawUnhandledException::WriteTo(SnapshotWriter* writer,
                                    intptr_t object_id,
                                    Snapshot::Kind kind,
                                    bool as_reference) {
  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteVMIsolateObject(kUnhandledExceptionCid);
  writer->WriteTags(writer->GetObjectTags(this));
  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawUnwindError* UnwindError::ReadFrom(SnapshotReader* reader,
                                      intptr_t object_id,
                                      intptr_t tags,
                                      Snapshot::Kind kind,
                                      bool as_reference) {
  UNREACHABLE();
  return UnwindError::null();
}


void RawUnwindError::WriteTo(SnapshotWriter* writer,
                             intptr_t object_id,
                             Snapshot::Kind kind,
                             bool as_reference) {
  UNREACHABLE();
}


RawInstance* Instance::ReadFrom(SnapshotReader* reader,
                                intptr_t object_id,
                                intptr_t tags,
                                Snapshot::Kind kind,
                                bool as_reference) {
  ASSERT(reader != NULL);

  // Create an Instance object or get canonical one if it is a canonical
  // constant.
  Instance& obj = Instance::ZoneHandle(reader->zone(), Instance::null());
  if (kind == Snapshot::kFull) {
    obj = reader->NewInstance();
    // Set the canonical bit.
    if (RawObject::IsCanonical(tags)) {
      obj.SetCanonical();
    }
  } else {
    obj ^= Object::Allocate(kInstanceCid,
                            Instance::InstanceSize(),
                            HEAP_SPACE(kind));
    if (RawObject::IsCanonical(tags)) {
      obj = obj.CheckAndCanonicalize(NULL);
    }
  }
  reader->AddBackRef(object_id, &obj, kIsDeserialized);

  return obj.raw();
}


void RawInstance::WriteTo(SnapshotWriter* writer,
                          intptr_t object_id,
                          Snapshot::Kind kind,
                          bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kInstanceCid);
  writer->WriteTags(writer->GetObjectTags(this));
}


RawInteger* Mint::ReadFrom(SnapshotReader* reader,
                           intptr_t object_id,
                           intptr_t tags,
                           Snapshot::Kind kind,
                           bool as_reference) {
  ASSERT(reader != NULL);

  // Read the 64 bit value for the object.
  int64_t value = reader->Read<int64_t>();

  // Check if the value could potentially fit in a Smi in our current
  // architecture, if so return the object as a Smi.
  if (Smi::IsValid(value)) {
    Smi& smi = Smi::ZoneHandle(reader->zone(),
                               Smi::New(static_cast<intptr_t>(value)));
    reader->AddBackRef(object_id, &smi, kIsDeserialized);
    return smi.raw();
  }

  // Create a Mint object or get canonical one if it is a canonical constant.
  Mint& mint = Mint::ZoneHandle(reader->zone(), Mint::null());
  if (kind == Snapshot::kFull) {
    mint = reader->NewMint(value);
    // Set the canonical bit.
    if (RawObject::IsCanonical(tags)) {
      mint.SetCanonical();
    }
  } else {
    // When reading a script snapshot we need to canonicalize only those object
    // references that are objects from the core library (loaded from a
    // full snapshot). Objects that are only in the script need not be
    // canonicalized as they are already canonical.
    // When reading a message snapshot we always have to canonicalize.
    if (RawObject::IsCanonical(tags)) {
      mint = Mint::NewCanonical(value);
      ASSERT(mint.IsCanonical());
    } else {
      mint = Mint::New(value, HEAP_SPACE(kind));
    }
  }
  reader->AddBackRef(object_id, &mint, kIsDeserialized);
  return mint.raw();
}


void RawMint::WriteTo(SnapshotWriter* writer,
                      intptr_t object_id,
                      Snapshot::Kind kind,
                      bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kMintCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the 64 bit value.
  writer->Write<int64_t>(ptr()->value_);
}


RawBigint* Bigint::ReadFrom(SnapshotReader* reader,
                            intptr_t object_id,
                            intptr_t tags,
                            Snapshot::Kind kind,
                            bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate bigint object.
  Bigint& obj = Bigint::ZoneHandle(reader->zone(), NEW_OBJECT(Bigint));
  reader->AddBackRef(object_id, &obj, kIsDeserialized);

  // Set all the object fields.
  READ_OBJECT_FIELDS(obj, obj.raw()->from(), obj.raw()->to(), kAsInlinedObject);

  // If it is a canonical constant make it one.
  // When reading a full snapshot we don't need to canonicalize the object
  // as it would already be a canonical object.
  // When reading a script snapshot or a message snapshot we always have
  // to canonicalize the object.
  if (RawObject::IsCanonical(tags)) {
    if (kind == Snapshot::kFull) {
      // Set the canonical bit.
      obj.SetCanonical();
    } else {
      obj ^= obj.CheckAndCanonicalize(NULL);
      ASSERT(!obj.IsNull());
      ASSERT(obj.IsCanonical());
    }
  }
  return obj.raw();
}


void RawBigint::WriteTo(SnapshotWriter* writer,
                        intptr_t object_id,
                        Snapshot::Kind kind,
                        bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kBigintCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsInlinedObject);
  visitor.VisitPointers(from(), to());
}


RawDouble* Double::ReadFrom(SnapshotReader* reader,
                            intptr_t object_id,
                            intptr_t tags,
                            Snapshot::Kind kind,
                            bool as_reference) {
  ASSERT(reader != NULL);
  ASSERT(kind != Snapshot::kMessage);
  // Read the double value for the object.
  double value = reader->ReadDouble();

  // Create a Double object or get canonical one if it is a canonical constant.
  Double& dbl = Double::ZoneHandle(reader->zone(), Double::null());
  if (kind == Snapshot::kFull) {
    dbl = reader->NewDouble(value);
    // Set the canonical bit.
    if (RawObject::IsCanonical(tags)) {
      dbl.SetCanonical();
    }
  } else {
    // When reading a script snapshot we need to canonicalize only those object
    // references that are objects from the core library (loaded from a
    // full snapshot). Objects that are only in the script need not be
    // canonicalized as they are already canonical.
    if (RawObject::IsCanonical(tags)) {
      dbl = Double::NewCanonical(value);
      ASSERT(dbl.IsCanonical());
    } else {
      dbl = Double::New(value, HEAP_SPACE(kind));
    }
  }
  reader->AddBackRef(object_id, &dbl, kIsDeserialized);
  return dbl.raw();
}


void RawDouble::WriteTo(SnapshotWriter* writer,
                        intptr_t object_id,
                        Snapshot::Kind kind,
                        bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kDoubleCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the double value.
  writer->WriteDouble(ptr()->value_);
}


RawString* String::ReadFrom(SnapshotReader* reader,
                            intptr_t object_id,
                            intptr_t tags,
                            Snapshot::Kind kind,
                            bool as_reference) {
  UNREACHABLE();  // String is an abstract class.
  return String::null();
}


void RawString::WriteTo(SnapshotWriter* writer,
                        intptr_t object_id,
                        Snapshot::Kind kind,
                        bool as_reference) {
  UNREACHABLE();  // String is an abstract class.
}


template<typename StringType, typename CharacterType, typename CallbackType>
void String::ReadFromImpl(SnapshotReader* reader,
                          String* str_obj,
                          intptr_t len,
                          intptr_t tags,
                          CallbackType new_symbol,
                          Snapshot::Kind kind) {
  ASSERT(reader != NULL);
  if (RawObject::IsCanonical(tags)) {
    // Set up canonical string object.
    ASSERT(reader != NULL);
    CharacterType* ptr = reader->zone()->Alloc<CharacterType>(len);
    for (intptr_t i = 0; i < len; i++) {
      ptr[i] = reader->Read<CharacterType>();
    }
    *str_obj ^= (*new_symbol)(ptr, len);
  } else {
    // Set up the string object.
    *str_obj = StringType::New(len, HEAP_SPACE(kind));
    str_obj->SetHash(0);  // Will get computed when needed.
    if (len == 0) {
      return;
    }
    NoSafepointScope no_safepoint;
    CharacterType* str_addr = StringType::CharAddr(*str_obj, 0);
    for (intptr_t i = 0; i < len; i++) {
      *str_addr = reader->Read<CharacterType>();
      str_addr++;
    }
  }
}


RawOneByteString* OneByteString::ReadFrom(SnapshotReader* reader,
                                          intptr_t object_id,
                                          intptr_t tags,
                                          Snapshot::Kind kind,
                                          bool as_reference) {
  if (reader->snapshot_code()) {
    ASSERT(kind == Snapshot::kFull);
    intptr_t offset = reader->Read<int32_t>();
    String& result = String::ZoneHandle(reader->zone());
    result ^= reader->GetObjectAt(offset);
    reader->AddBackRef(object_id, &result, kIsDeserialized);
    return raw(result);
  }
  // Read the length so that we can determine instance size to allocate.
  ASSERT(reader != NULL);
  intptr_t len = reader->ReadSmiValue();
  intptr_t hash = reader->ReadSmiValue();
  String& str_obj = String::ZoneHandle(reader->zone(), String::null());

  if (kind == Snapshot::kFull) {
    // We currently only expect the Dart mutator to read snapshots.
    reader->isolate()->AssertCurrentThreadIsMutator();
    ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0);
    RawOneByteString* obj = reader->NewOneByteString(len);
    str_obj = obj;
    if (RawObject::IsCanonical(tags)) {
      str_obj.SetCanonical();
    }
    str_obj.SetHash(hash);
    if (len > 0) {
      uint8_t* raw_ptr = CharAddr(str_obj, 0);
      reader->ReadBytes(raw_ptr, len);
    }
    ASSERT((hash == 0) || (String::Hash(str_obj, 0, str_obj.Length()) == hash));
  } else {
    String::ReadFromImpl<OneByteString, uint8_t>(
        reader, &str_obj, len, tags, Symbols::FromLatin1, kind);
  }
  reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
  return raw(str_obj);
}


RawTwoByteString* TwoByteString::ReadFrom(SnapshotReader* reader,
                                          intptr_t object_id,
                                          intptr_t tags,
                                          Snapshot::Kind kind,
                                          bool as_reference) {
  // Read the length so that we can determine instance size to allocate.
  ASSERT(reader != NULL);
  intptr_t len = reader->ReadSmiValue();
  intptr_t hash = reader->ReadSmiValue();
  String& str_obj = String::ZoneHandle(reader->zone(), String::null());

  if (kind == Snapshot::kFull) {
    RawTwoByteString* obj = reader->NewTwoByteString(len);
    str_obj = obj;
    if (RawObject::IsCanonical(tags)) {
      str_obj.SetCanonical();
    }
    str_obj.SetHash(hash);
    NoSafepointScope no_safepoint;
    uint16_t* raw_ptr = (len > 0)? CharAddr(str_obj, 0) : NULL;
    for (intptr_t i = 0; i < len; i++) {
      ASSERT(CharAddr(str_obj, i) == raw_ptr);  // Will trigger assertions.
      *raw_ptr = reader->Read<uint16_t>();
      raw_ptr += 1;
    }
    ASSERT(String::Hash(str_obj, 0, str_obj.Length()) == hash);
  } else {
    String::ReadFromImpl<TwoByteString, uint16_t>(
        reader, &str_obj, len, tags, Symbols::FromUTF16, kind);
  }
  reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
  return raw(str_obj);
}


template<typename T>
static void StringWriteTo(SnapshotWriter* writer,
                          intptr_t object_id,
                          Snapshot::Kind kind,
                          intptr_t class_id,
                          intptr_t tags,
                          RawSmi* length,
                          RawSmi* hash,
                          T* data) {
  ASSERT(writer != NULL);
  intptr_t len = Smi::Value(length);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(class_id);
  writer->WriteTags(tags);

  // Write out the length field.
  writer->Write<RawObject*>(length);

  // Write out the hash field.
  writer->Write<RawObject*>(hash);

  // Write out the string.
  if (len > 0) {
    if (class_id == kOneByteStringCid) {
      writer->WriteBytes(reinterpret_cast<const uint8_t*>(data), len);
    } else {
      for (intptr_t i = 0; i < len; i++) {
        writer->Write(data[i]);
      }
    }
  }
}


void RawOneByteString::WriteTo(SnapshotWriter* writer,
                               intptr_t object_id,
                               Snapshot::Kind kind,
                               bool as_reference) {
  if (writer->snapshot_code()) {
    ASSERT(writer->snapshot_code());
    ASSERT(kind == Snapshot::kFull);
    // Assert that hash is computed.
    if (ptr()->hash_ == NULL) {
      ptr()->hash_ = Smi::New(String::Hash(ptr()->data(),
                                           Smi::Value(ptr()->length_)));
    }
    ASSERT(ptr()->hash_ != NULL);
    // Write out the serialization header value for this object.
    writer->WriteInlinedObjectHeader(object_id);
    writer->WriteIndexedObject(kOneByteStringCid);
    writer->WriteTags(writer->GetObjectTags(this));
    writer->Write<int32_t>(writer->GetObjectId(this));
    return;
  }
  StringWriteTo(writer,
                object_id,
                kind,
                kOneByteStringCid,
                writer->GetObjectTags(this),
                ptr()->length_,
                ptr()->hash_,
                ptr()->data());
}


void RawTwoByteString::WriteTo(SnapshotWriter* writer,
                               intptr_t object_id,
                               Snapshot::Kind kind,
                               bool as_reference) {
  StringWriteTo(writer,
                object_id,
                kind,
                kTwoByteStringCid,
                writer->GetObjectTags(this),
                ptr()->length_,
                ptr()->hash_,
                ptr()->data());
}


RawExternalOneByteString* ExternalOneByteString::ReadFrom(
    SnapshotReader* reader,
    intptr_t object_id,
    intptr_t tags,
    Snapshot::Kind kind,
    bool as_reference) {
  UNREACHABLE();
  return ExternalOneByteString::null();
}


RawExternalTwoByteString* ExternalTwoByteString::ReadFrom(
    SnapshotReader* reader,
    intptr_t object_id,
    intptr_t tags,
    Snapshot::Kind kind,
    bool as_reference) {
  UNREACHABLE();
  return ExternalTwoByteString::null();
}


void RawExternalOneByteString::WriteTo(SnapshotWriter* writer,
                                       intptr_t object_id,
                                       Snapshot::Kind kind,
                                       bool as_reference) {
  // Serialize as a non-external one byte string.
  StringWriteTo(writer,
                object_id,
                kind,
                kOneByteStringCid,
                writer->GetObjectTags(this),
                ptr()->length_,
                ptr()->hash_,
                ptr()->external_data_->data());
}


void RawExternalTwoByteString::WriteTo(SnapshotWriter* writer,
                                       intptr_t object_id,
                                       Snapshot::Kind kind,
                                       bool as_reference) {
  // Serialize as a non-external two byte string.
  StringWriteTo(writer,
                object_id,
                kind,
                kTwoByteStringCid,
                writer->GetObjectTags(this),
                ptr()->length_,
                ptr()->hash_,
                ptr()->external_data_->data());
}


RawBool* Bool::ReadFrom(SnapshotReader* reader,
                        intptr_t object_id,
                        intptr_t tags,
                        Snapshot::Kind kind,
                        bool as_reference) {
  UNREACHABLE();
  return Bool::null();
}


void RawBool::WriteTo(SnapshotWriter* writer,
                      intptr_t object_id,
                      Snapshot::Kind kind,
                      bool as_reference) {
  UNREACHABLE();
}


RawArray* Array::ReadFrom(SnapshotReader* reader,
                          intptr_t object_id,
                          intptr_t tags,
                          Snapshot::Kind kind,
                          bool as_reference) {
  ASSERT(reader != NULL);

  // Read the length so that we can determine instance size to allocate.
  intptr_t len = reader->ReadSmiValue();
  Array* array = NULL;
  DeserializeState state;
  if (!as_reference) {
    array = reinterpret_cast<Array*>(reader->GetBackRef(object_id));
    state = kIsDeserialized;
  } else {
    state = kIsNotDeserialized;
  }
  if (array == NULL) {
    array = &(Array::ZoneHandle(reader->zone(),
                                NEW_OBJECT_WITH_LEN_SPACE(Array, len, kind)));
    reader->AddBackRef(object_id, array, state);
  }
  if (!as_reference) {
    // Read all the individual elements for inlined objects.
    ASSERT(!RawObject::IsCanonical(tags));
    reader->ArrayReadFrom(object_id, *array, len, tags);
  }
  return array->raw();
}


RawImmutableArray* ImmutableArray::ReadFrom(SnapshotReader* reader,
                                            intptr_t object_id,
                                            intptr_t tags,
                                            Snapshot::Kind kind,
                                            bool as_reference) {
  ASSERT(reader != NULL);

  // Read the length so that we can determine instance size to allocate.
  intptr_t len = reader->ReadSmiValue();
  Array* array = NULL;
  DeserializeState state;
  if (!as_reference) {
    array = reinterpret_cast<Array*>(reader->GetBackRef(object_id));
    state = kIsDeserialized;
  } else {
    state = kIsNotDeserialized;
  }
  if (array == NULL) {
    array = &(Array::ZoneHandle(
        reader->zone(),
        NEW_OBJECT_WITH_LEN_SPACE(ImmutableArray, len, kind)));
    reader->AddBackRef(object_id, array, state);
  }
  if (!as_reference) {
    // Read all the individual elements for inlined objects.
    reader->ArrayReadFrom(object_id, *array, len, tags);
    if (RawObject::IsCanonical(tags)) {
      if (kind == Snapshot::kFull) {
        array->SetCanonical();
      } else {
        *array ^= array->CheckAndCanonicalize(NULL);
      }
    }
  }
  return raw(*array);
}


void RawArray::WriteTo(SnapshotWriter* writer,
                       intptr_t object_id,
                       Snapshot::Kind kind,
                       bool as_reference) {
  ASSERT(!this->IsCanonical());
  writer->ArrayWriteTo(object_id,
                       kArrayCid,
                       writer->GetObjectTags(this),
                       ptr()->length_,
                       ptr()->type_arguments_,
                       ptr()->data(),
                       as_reference);
}


void RawImmutableArray::WriteTo(SnapshotWriter* writer,
                                intptr_t object_id,
                                Snapshot::Kind kind,
                                bool as_reference) {
  writer->ArrayWriteTo(object_id,
                       kImmutableArrayCid,
                       writer->GetObjectTags(this),
                       ptr()->length_,
                       ptr()->type_arguments_,
                       ptr()->data(),
                       as_reference);
}


RawGrowableObjectArray* GrowableObjectArray::ReadFrom(SnapshotReader* reader,
                                                      intptr_t object_id,
                                                      intptr_t tags,
                                                      Snapshot::Kind kind,
                                                      bool as_reference) {
  ASSERT(reader != NULL);

  // Read the length so that we can determine instance size to allocate.
  GrowableObjectArray& array = GrowableObjectArray::ZoneHandle(
      reader->zone(), GrowableObjectArray::null());
  if (kind == Snapshot::kFull) {
    array = reader->NewGrowableObjectArray();
  } else {
    array = GrowableObjectArray::New(0, HEAP_SPACE(kind));
  }
  reader->AddBackRef(object_id, &array, kIsDeserialized);

  // Read type arguments of growable array object.
  const intptr_t typeargs_offset =
      GrowableObjectArray::type_arguments_offset() / kWordSize;
  *reader->TypeArgumentsHandle() ^=
      reader->ReadObjectImpl(kAsInlinedObject, object_id, typeargs_offset);
  array.StorePointer(&array.raw_ptr()->type_arguments_,
                     reader->TypeArgumentsHandle()->raw());

  // Read length of growable array object.
  array.SetLength(reader->ReadSmiValue());

  // Read the backing array of growable array object.
  *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsReference);
  array.SetData(*(reader->ArrayHandle()));

  return array.raw();
}


void RawGrowableObjectArray::WriteTo(SnapshotWriter* writer,
                                     intptr_t object_id,
                                     Snapshot::Kind kind,
                                     bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kGrowableObjectArrayCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the type arguments field.
  writer->WriteObjectImpl(ptr()->type_arguments_, kAsInlinedObject);

  // Write out the used length field.
  writer->Write<RawObject*>(ptr()->length_);

  // Write out the Array object.
  writer->WriteObjectImpl(ptr()->data_, kAsReference);
}


RawLinkedHashMap* LinkedHashMap::ReadFrom(SnapshotReader* reader,
                                          intptr_t object_id,
                                          intptr_t tags,
                                          Snapshot::Kind kind,
                                          bool as_reference) {
  ASSERT(reader != NULL);

  LinkedHashMap& map = LinkedHashMap::ZoneHandle(
      reader->zone(), LinkedHashMap::null());
  if ((kind == Snapshot::kFull && !reader->snapshot_code()) ||
      kind == Snapshot::kScript) {
    // The immutable maps that seed map literals are not yet VM-internal, so
    // we don't reach this.
    UNREACHABLE();
  } else {
    // Since the map might contain itself as a key or value, allocate first.
    if (kind == Snapshot::kFull) {
      map = reader->NewLinkedHashMap();
    } else {
      map = LinkedHashMap::NewUninitialized(HEAP_SPACE(kind));
    }
  }
  reader->AddBackRef(object_id, &map, kIsDeserialized);

  // Read the type arguments.
  const intptr_t typeargs_offset =
      GrowableObjectArray::type_arguments_offset() / kWordSize;
  *reader->TypeArgumentsHandle() ^=
      reader->ReadObjectImpl(kAsInlinedObject, object_id, typeargs_offset);
  map.SetTypeArguments(*reader->TypeArgumentsHandle());

  // Read the number of key/value pairs.
  intptr_t len = reader->ReadSmiValue();
  intptr_t used_data = (len << 1);
  map.SetUsedData(used_data);

  // Allocate the data array.
  intptr_t data_size = Utils::Maximum(
      Utils::RoundUpToPowerOfTwo(used_data),
      static_cast<uintptr_t>(LinkedHashMap::kInitialIndexSize));
  Array& data = Array::ZoneHandle(reader->zone(),
                                  NEW_OBJECT_WITH_LEN_SPACE(Array,
                                                            data_size,
                                                            kind));
  map.SetData(data);
  map.SetDeletedKeys(0);

  // The index and hashMask is regenerated by the maps themselves on demand.
  // Thus, the index will probably be allocated in new space (unless it's huge).
  // TODO(koda): Eagerly rehash here when no keys have user-defined '==', and
  // in particular, if/when (const) maps are needed in the VM isolate snapshot.
  ASSERT(reader->isolate() != Dart::vm_isolate());
  map.SetHashMask(0);  // Prefer sentinel 0 over null for better type feedback.

  // Read the keys and values.
  bool read_as_reference = RawObject::IsCanonical(tags) ? false : true;
  for (intptr_t i = 0; i < used_data; i++) {
    *reader->PassiveObjectHandle() = reader->ReadObjectImpl(read_as_reference);
    data.SetAt(i, *reader->PassiveObjectHandle());
  }
  return map.raw();
}


void RawLinkedHashMap::WriteTo(SnapshotWriter* writer,
                               intptr_t object_id,
                               Snapshot::Kind kind,
                               bool as_reference) {
  if ((kind == Snapshot::kFull && !writer->snapshot_code()) ||
      kind == Snapshot::kScript) {
    // The immutable maps that seed map literals are not yet VM-internal, so
    // we don't reach this.
  }
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kLinkedHashMapCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the type arguments.
  writer->WriteObjectImpl(ptr()->type_arguments_, kAsInlinedObject);

  const intptr_t used_data = Smi::Value(ptr()->used_data_);
  ASSERT((used_data & 1) == 0);  // Keys + values, so must be even.
  const intptr_t deleted_keys = Smi::Value(ptr()->deleted_keys_);

  // Write out the number of (not deleted) key/value pairs that will follow.
  writer->Write<RawObject*>(Smi::New((used_data >> 1) - deleted_keys));

  // Write out the keys and values.
  const bool write_as_reference = this->IsCanonical() ? false : true;
  RawArray* data_array = ptr()->data_;
  RawObject** data_elements = data_array->ptr()->data();
  ASSERT(used_data <= Smi::Value(data_array->ptr()->length_));
#if defined(DEBUG)
  intptr_t deleted_keys_found = 0;
#endif  // DEBUG
  for (intptr_t i = 0; i < used_data; i += 2) {
    RawObject* key = data_elements[i];
    if (key == data_array) {
#if defined(DEBUG)
      ++deleted_keys_found;
#endif  // DEBUG
      continue;
    }
    RawObject* value = data_elements[i + 1];
    writer->WriteObjectImpl(key, write_as_reference);
    writer->WriteObjectImpl(value, write_as_reference);
  }
  DEBUG_ASSERT(deleted_keys_found == deleted_keys);
}


RawFloat32x4* Float32x4::ReadFrom(SnapshotReader* reader,
                                  intptr_t object_id,
                                  intptr_t tags,
                                  Snapshot::Kind kind,
                                  bool as_reference) {
  ASSERT(reader != NULL);
  // Read the values.
  float value0 = reader->Read<float>();
  float value1 = reader->Read<float>();
  float value2 = reader->Read<float>();
  float value3 = reader->Read<float>();

  // Create a Float32x4 object.
  Float32x4& simd = Float32x4::ZoneHandle(reader->zone(),
                                          Float32x4::null());
  if (kind == Snapshot::kFull) {
    simd = reader->NewFloat32x4(value0, value1, value2, value3);
  } else {
    simd = Float32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
  }
  reader->AddBackRef(object_id, &simd, kIsDeserialized);
  return simd.raw();
}


void RawFloat32x4::WriteTo(SnapshotWriter* writer,
                           intptr_t object_id,
                           Snapshot::Kind kind,
                           bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kFloat32x4Cid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the float values.
  writer->Write<float>(ptr()->value_[0]);
  writer->Write<float>(ptr()->value_[1]);
  writer->Write<float>(ptr()->value_[2]);
  writer->Write<float>(ptr()->value_[3]);
}


RawInt32x4* Int32x4::ReadFrom(SnapshotReader* reader,
                              intptr_t object_id,
                              intptr_t tags,
                              Snapshot::Kind kind,
                              bool as_reference) {
  ASSERT(reader != NULL);
  // Read the values.
  uint32_t value0 = reader->Read<uint32_t>();
  uint32_t value1 = reader->Read<uint32_t>();
  uint32_t value2 = reader->Read<uint32_t>();
  uint32_t value3 = reader->Read<uint32_t>();

  // Create a Float32x4 object.
  Int32x4& simd = Int32x4::ZoneHandle(reader->zone(), Int32x4::null());

  if (kind == Snapshot::kFull) {
    simd = reader->NewInt32x4(value0, value1, value2, value3);
  } else {
    simd = Int32x4::New(value0, value1, value2, value3, HEAP_SPACE(kind));
  }
  reader->AddBackRef(object_id, &simd, kIsDeserialized);
  return simd.raw();
}


void RawInt32x4::WriteTo(SnapshotWriter* writer,
                         intptr_t object_id,
                         Snapshot::Kind kind,
                         bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kInt32x4Cid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the mask values.
  writer->Write<uint32_t>(ptr()->value_[0]);
  writer->Write<uint32_t>(ptr()->value_[1]);
  writer->Write<uint32_t>(ptr()->value_[2]);
  writer->Write<uint32_t>(ptr()->value_[3]);
}


RawFloat64x2* Float64x2::ReadFrom(SnapshotReader* reader,
                                  intptr_t object_id,
                                  intptr_t tags,
                                  Snapshot::Kind kind,
                                  bool as_reference) {
  ASSERT(reader != NULL);
  // Read the values.
  double value0 = reader->Read<double>();
  double value1 = reader->Read<double>();

  // Create a Float64x2 object.
  Float64x2& simd = Float64x2::ZoneHandle(reader->zone(),
                                          Float64x2::null());
  if (kind == Snapshot::kFull) {
    simd = reader->NewFloat64x2(value0, value1);
  } else {
    simd = Float64x2::New(value0, value1, HEAP_SPACE(kind));
  }
  reader->AddBackRef(object_id, &simd, kIsDeserialized);
  return simd.raw();
}


void RawFloat64x2::WriteTo(SnapshotWriter* writer,
                           intptr_t object_id,
                           Snapshot::Kind kind,
                           bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kFloat64x2Cid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the float values.
  writer->Write<double>(ptr()->value_[0]);
  writer->Write<double>(ptr()->value_[1]);
}


#define TYPED_DATA_READ(setter, type)                                          \
  for (intptr_t i = 0; i < length_in_bytes; i += element_size) {               \
    result.Set##setter(i, reader->Read<type>());                               \
  }                                                                            \


RawTypedData* TypedData::ReadFrom(SnapshotReader* reader,
                                  intptr_t object_id,
                                  intptr_t tags,
                                  Snapshot::Kind kind,
                                  bool as_reference) {
  ASSERT(reader != NULL);

  intptr_t cid = RawObject::ClassIdTag::decode(tags);
  intptr_t len = reader->ReadSmiValue();
  TypedData& result = TypedData::ZoneHandle(reader->zone(),
      (kind == Snapshot::kFull) ? reader->NewTypedData(cid, len)
                                : TypedData::New(cid, len, HEAP_SPACE(kind)));
  reader->AddBackRef(object_id, &result, kIsDeserialized);

  // Setup the array elements.
  intptr_t element_size = ElementSizeInBytes(cid);
  intptr_t length_in_bytes = len * element_size;
  switch (cid) {
    case kTypedDataInt8ArrayCid:
    case kTypedDataUint8ArrayCid:
    case kTypedDataUint8ClampedArrayCid: {
      NoSafepointScope no_safepoint;
      uint8_t* data = reinterpret_cast<uint8_t*>(result.DataAddr(0));
      reader->ReadBytes(data, length_in_bytes);
      break;
    }
    case kTypedDataInt16ArrayCid:
      TYPED_DATA_READ(Int16, int16_t);
      break;
    case kTypedDataUint16ArrayCid:
      TYPED_DATA_READ(Uint16, uint16_t);
      break;
    case kTypedDataInt32ArrayCid:
      TYPED_DATA_READ(Int32, int32_t);
      break;
    case kTypedDataUint32ArrayCid:
      TYPED_DATA_READ(Uint32, uint32_t);
      break;
    case kTypedDataInt64ArrayCid:
      TYPED_DATA_READ(Int64, int64_t);
      break;
    case kTypedDataUint64ArrayCid:
      TYPED_DATA_READ(Uint64, uint64_t);
      break;
    case kTypedDataFloat32ArrayCid:
      TYPED_DATA_READ(Float32, float);
      break;
    case kTypedDataFloat64ArrayCid:
      TYPED_DATA_READ(Float64, double);
      break;
    default:
      UNREACHABLE();
  }
  // If it is a canonical constant make it one.
  // When reading a full snapshot we don't need to canonicalize the object
  // as it would already be a canonical object.
  // When reading a script snapshot or a message snapshot we always have
  // to canonicalize the object.
  if (RawObject::IsCanonical(tags)) {
    if (kind == Snapshot::kFull) {
      // Set the canonical bit.
      result.SetCanonical();
    } else {
      result ^= result.CheckAndCanonicalize(NULL);
      ASSERT(!result.IsNull());
      ASSERT(result.IsCanonical());
    }
  }
  return result.raw();
}
#undef TYPED_DATA_READ


RawExternalTypedData* ExternalTypedData::ReadFrom(SnapshotReader* reader,
                                                  intptr_t object_id,
                                                  intptr_t tags,
                                                  Snapshot::Kind kind,
                                                  bool as_reference) {
  ASSERT(kind != Snapshot::kFull);
  intptr_t cid = RawObject::ClassIdTag::decode(tags);
  intptr_t length = reader->ReadSmiValue();
  uint8_t* data = reinterpret_cast<uint8_t*>(reader->ReadRawPointerValue());
  ExternalTypedData& obj = ExternalTypedData::ZoneHandle(
      ExternalTypedData::New(cid, data, length));
  reader->AddBackRef(object_id, &obj, kIsDeserialized);
  void* peer = reinterpret_cast<void*>(reader->ReadRawPointerValue());
  Dart_WeakPersistentHandleFinalizer callback =
      reinterpret_cast<Dart_WeakPersistentHandleFinalizer>(
          reader->ReadRawPointerValue());
  obj.AddFinalizer(peer, callback);
  return obj.raw();
}


#define TYPED_DATA_WRITE(type)                                                 \
  {                                                                            \
    type* data = reinterpret_cast<type*>(ptr()->data());                       \
    for (intptr_t i = 0; i < len; i++) {                                       \
      writer->Write(data[i]);                                                  \
    }                                                                          \
  }                                                                            \


void RawTypedData::WriteTo(SnapshotWriter* writer,
                           intptr_t object_id,
                           Snapshot::Kind kind,
                           bool as_reference) {
  ASSERT(writer != NULL);
  intptr_t cid = this->GetClassId();
  intptr_t len = Smi::Value(ptr()->length_);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(cid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out the length field.
  writer->Write<RawObject*>(ptr()->length_);

  // Write out the array elements.
  switch (cid) {
    case kTypedDataInt8ArrayCid:
    case kTypedDataUint8ArrayCid:
    case kTypedDataUint8ClampedArrayCid: {
      uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
      writer->WriteBytes(data, len);
      break;
    }
    case kTypedDataInt16ArrayCid:
      TYPED_DATA_WRITE(int16_t);
      break;
    case kTypedDataUint16ArrayCid:
      TYPED_DATA_WRITE(uint16_t);
      break;
    case kTypedDataInt32ArrayCid:
      TYPED_DATA_WRITE(int32_t);
      break;
    case kTypedDataUint32ArrayCid:
      TYPED_DATA_WRITE(uint32_t);
      break;
    case kTypedDataInt64ArrayCid:
      TYPED_DATA_WRITE(int64_t);
      break;
    case kTypedDataUint64ArrayCid:
      TYPED_DATA_WRITE(uint64_t);
      break;
    case kTypedDataFloat32ArrayCid:
      TYPED_DATA_WRITE(float);  // NOLINT.
      break;
    case kTypedDataFloat64ArrayCid:
      TYPED_DATA_WRITE(double);  // NOLINT.
      break;
    default:
      UNREACHABLE();
  }
}


#define TYPED_EXT_DATA_WRITE(type)                                             \
  {                                                                            \
    type* data = reinterpret_cast<type*>(ptr()->data_);                        \
    for (intptr_t i = 0; i < len; i++) {                                       \
      writer->Write(data[i]);                                                  \
    }                                                                          \
  }                                                                            \


#define EXT_TYPED_DATA_WRITE(cid, type)                                        \
  writer->WriteIndexedObject(cid);                                             \
  writer->WriteTags(writer->GetObjectTags(this));                              \
  writer->Write<RawObject*>(ptr()->length_);                                   \
  TYPED_EXT_DATA_WRITE(type)                                                   \


void RawExternalTypedData::WriteTo(SnapshotWriter* writer,
                                   intptr_t object_id,
                                   Snapshot::Kind kind,
                                   bool as_reference) {
  ASSERT(writer != NULL);
  intptr_t cid = this->GetClassId();
  intptr_t len = Smi::Value(ptr()->length_);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  switch (cid) {
    case kExternalTypedDataInt8ArrayCid:
      EXT_TYPED_DATA_WRITE(kTypedDataInt8ArrayCid, int8_t);
      break;
    case kExternalTypedDataUint8ArrayCid:
      EXT_TYPED_DATA_WRITE(kTypedDataUint8ArrayCid, uint8_t);
      break;
    case kExternalTypedDataUint8ClampedArrayCid:
      EXT_TYPED_DATA_WRITE(kTypedDataUint8ClampedArrayCid, uint8_t);
      break;
    case kExternalTypedDataInt16ArrayCid:
      EXT_TYPED_DATA_WRITE(kTypedDataInt16ArrayCid, int16_t);
      break;
    case kExternalTypedDataUint16ArrayCid:
      EXT_TYPED_DATA_WRITE(kTypedDataUint16ArrayCid, uint16_t);
      break;
    case kExternalTypedDataInt32ArrayCid:
      EXT_TYPED_DATA_WRITE(kTypedDataInt32ArrayCid, int32_t);
      break;
    case kExternalTypedDataUint32ArrayCid:
      EXT_TYPED_DATA_WRITE(kTypedDataUint32ArrayCid, uint32_t);
      break;
    case kExternalTypedDataInt64ArrayCid:
      EXT_TYPED_DATA_WRITE(kTypedDataInt64ArrayCid, int64_t);
      break;
    case kExternalTypedDataUint64ArrayCid:
      EXT_TYPED_DATA_WRITE(kTypedDataUint64ArrayCid, uint64_t);
      break;
    case kExternalTypedDataFloat32ArrayCid:
      EXT_TYPED_DATA_WRITE(kTypedDataFloat32ArrayCid, float);  // NOLINT.
      break;
    case kExternalTypedDataFloat64ArrayCid:
      EXT_TYPED_DATA_WRITE(kTypedDataFloat64ArrayCid, double);  // NOLINT.
      break;
    default:
      UNREACHABLE();
  }
}
#undef TYPED_DATA_WRITE
#undef EXT_TYPED_DATA_WRITE


RawCapability* Capability::ReadFrom(SnapshotReader* reader,
                                    intptr_t object_id,
                                    intptr_t tags,
                                    Snapshot::Kind kind,
                                    bool as_reference) {
  uint64_t id = reader->Read<uint64_t>();

  Capability& result = Capability::ZoneHandle(reader->zone(),
                                              Capability::New(id));
  reader->AddBackRef(object_id, &result, kIsDeserialized);
  return result.raw();
}


void RawCapability::WriteTo(SnapshotWriter* writer,
                            intptr_t object_id,
                            Snapshot::Kind kind,
                            bool as_reference) {
  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kCapabilityCid);
  writer->WriteTags(writer->GetObjectTags(this));

  writer->Write<uint64_t>(ptr()->id_);
}


RawReceivePort* ReceivePort::ReadFrom(SnapshotReader* reader,
                                      intptr_t object_id,
                                      intptr_t tags,
                                      Snapshot::Kind kind,
                                      bool as_reference) {
  UNREACHABLE();
  return ReceivePort::null();
}


void RawReceivePort::WriteTo(SnapshotWriter* writer,
                             intptr_t object_id,
                             Snapshot::Kind kind,
                             bool as_reference) {
  if (kind == Snapshot::kMessage) {
    // We do not allow objects with native fields in an isolate message.
    writer->SetWriteException(Exceptions::kArgument,
                              "Illegal argument in isolate message"
                              " : (object is a RawReceivePort)");
  } else {
    UNREACHABLE();
  }
}


RawSendPort* SendPort::ReadFrom(SnapshotReader* reader,
                                intptr_t object_id,
                                intptr_t tags,
                                Snapshot::Kind kind,
                                bool as_reference) {
  ASSERT(kind == Snapshot::kMessage || reader->snapshot_code());

  uint64_t id = reader->Read<uint64_t>();
  uint64_t origin_id = reader->Read<uint64_t>();

  SendPort& result = SendPort::ZoneHandle(reader->zone());
  if (reader->snapshot_code()) {
    // TODO(rmacnak): Reset fields in precompiled snapshots and assert
    // this is unreachable.
  } else {
    result = SendPort::New(id, origin_id);
  }
  reader->AddBackRef(object_id, &result, kIsDeserialized);
  return result.raw();
}


void RawSendPort::WriteTo(SnapshotWriter* writer,
                          intptr_t object_id,
                          Snapshot::Kind kind,
                          bool as_reference) {
  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kSendPortCid);
  writer->WriteTags(writer->GetObjectTags(this));

  writer->Write<uint64_t>(ptr()->id_);
  writer->Write<uint64_t>(ptr()->origin_id_);
}


RawStacktrace* Stacktrace::ReadFrom(SnapshotReader* reader,
                                    intptr_t object_id,
                                    intptr_t tags,
                                    Snapshot::Kind kind,
                                    bool as_reference) {
  if (kind == Snapshot::kFull) {
    Stacktrace& result = Stacktrace::ZoneHandle(reader->zone(),
                                                reader->NewStacktrace());
    reader->AddBackRef(object_id, &result, kIsDeserialized);

    bool expand_inlined = reader->Read<bool>();
    result.set_expand_inlined(expand_inlined);

    // Set all the object fields.
    READ_OBJECT_FIELDS(result,
                       result.raw()->from(), result.raw()->to(),
                       kAsReference);

    return result.raw();
  }
  UNREACHABLE();  // Stacktraces are not sent in a snapshot.
  return Stacktrace::null();
}


void RawStacktrace::WriteTo(SnapshotWriter* writer,
                            intptr_t object_id,
                            Snapshot::Kind kind,
                            bool as_reference) {
  if (kind == Snapshot::kFull) {
    ASSERT(writer != NULL);
    ASSERT(this == Isolate::Current()->object_store()->
           preallocated_stack_trace());

    // Write out the serialization header value for this object.
    writer->WriteInlinedObjectHeader(object_id);

    // Write out the class and tags information.
    writer->WriteIndexedObject(kStacktraceCid);
    writer->WriteTags(writer->GetObjectTags(this));

    writer->Write(ptr()->expand_inlined_);

    // Write out all the object pointer fields.
    SnapshotWriterVisitor visitor(writer, kAsReference);
    visitor.VisitPointers(from(), to());
  } else {
    // Stacktraces are not allowed in other snapshot forms.
    writer->SetWriteException(Exceptions::kArgument,
                              "Illegal argument in isolate message"
                              " : (object is a stacktrace)");
  }
}


RawRegExp* RegExp::ReadFrom(SnapshotReader* reader,
                            intptr_t object_id,
                            intptr_t tags,
                            Snapshot::Kind kind,
                            bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate RegExp object.
  RegExp& regex = RegExp::ZoneHandle(reader->zone(), NEW_OBJECT(RegExp));
  reader->AddBackRef(object_id, &regex, kIsDeserialized);

  // Read and Set all the other fields.
  regex.StoreSmi(&regex.raw_ptr()->num_bracket_expressions_,
                 reader->ReadAsSmi());
  *reader->StringHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
  regex.set_pattern(*reader->StringHandle());
  regex.StoreNonPointer(&regex.raw_ptr()->num_registers_,
                        reader->Read<int32_t>());
  regex.StoreNonPointer(&regex.raw_ptr()->type_flags_,
                        reader->Read<int8_t>());

  // TODO(18854): Need to implement a way of recreating the irrexp functions.
  const Function& no_function = Function::Handle(reader->zone());
  regex.set_function(kOneByteStringCid, no_function);
  regex.set_function(kTwoByteStringCid, no_function);
  regex.set_function(kExternalOneByteStringCid, no_function);
  regex.set_function(kExternalTwoByteStringCid, no_function);

  const TypedData& no_bytecode = TypedData::Handle(reader->zone());
  regex.set_bytecode(true, no_bytecode);
  regex.set_bytecode(false, no_bytecode);

  return regex.raw();
}


void RawRegExp::WriteTo(SnapshotWriter* writer,
                        intptr_t object_id,
                        Snapshot::Kind kind,
                        bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kRegExpCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the other fields.
  writer->Write<RawObject*>(ptr()->num_bracket_expressions_);
  writer->WriteObjectImpl(ptr()->pattern_, kAsInlinedObject);
  writer->Write<int32_t>(ptr()->num_registers_);
  writer->Write<int8_t>(ptr()->type_flags_);
}


RawWeakProperty* WeakProperty::ReadFrom(SnapshotReader* reader,
                                        intptr_t object_id,
                                        intptr_t tags,
                                        Snapshot::Kind kind,
                                        bool as_reference) {
  ASSERT(reader != NULL);

  // Allocate the weak property object.
  WeakProperty& weak_property = WeakProperty::ZoneHandle(
      reader->zone(), NEW_OBJECT(WeakProperty));
  reader->AddBackRef(object_id, &weak_property, kIsDeserialized);

  // Set all the object fields.
  READ_OBJECT_FIELDS(weak_property,
                     weak_property.raw()->from(), weak_property.raw()->to(),
                     kAsReference);

  return weak_property.raw();
}


void RawWeakProperty::WriteTo(SnapshotWriter* writer,
                              intptr_t object_id,
                              Snapshot::Kind kind,
                              bool as_reference) {
  ASSERT(writer != NULL);

  // Write out the serialization header value for this object.
  writer->WriteInlinedObjectHeader(object_id);

  // Write out the class and tags information.
  writer->WriteIndexedObject(kWeakPropertyCid);
  writer->WriteTags(writer->GetObjectTags(this));

  // Write out all the object pointer fields.
  SnapshotWriterVisitor visitor(writer, kAsReference);
  visitor.VisitPointers(from(), to());
}


RawMirrorReference* MirrorReference::ReadFrom(SnapshotReader* reader,
                                              intptr_t object_id,
                                              intptr_t tags,
                                              Snapshot::Kind kind,
                                              bool as_referenec) {
  UNREACHABLE();
  return MirrorReference::null();
}


void RawMirrorReference::WriteTo(SnapshotWriter* writer,
                                 intptr_t object_id,
                                 Snapshot::Kind kind,
                                 bool as_reference) {
  if (kind == Snapshot::kMessage) {
    // We do not allow objects with native fields in an isolate message.
    writer->SetWriteException(Exceptions::kArgument,
                              "Illegal argument in isolate message"
                              " : (object is a MirrorReference)");
  } else {
    UNREACHABLE();
  }
}


RawUserTag* UserTag::ReadFrom(SnapshotReader* reader,
                              intptr_t object_id,
                              intptr_t tags,
                              Snapshot::Kind kind,
                              bool as_reference) {
  UNREACHABLE();
  return UserTag::null();
}


void RawUserTag::WriteTo(SnapshotWriter* writer,
                         intptr_t object_id,
                         Snapshot::Kind kind,
                         bool as_reference) {
  if (kind == Snapshot::kMessage) {
    // We do not allow objects with native fields in an isolate message.
    writer->SetWriteException(Exceptions::kArgument,
                              "Illegal argument in isolate message"
                              " : (object is a UserTag)");
  } else {
    UNREACHABLE();
  }
}

}  // namespace dart
