// 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)                                                       \
  ((Snapshot::IsFull(kind)) ? reader->New##type() : type::New())

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

#define NEW_OBJECT_WITH_LEN_SPACE(type, len, kind)                             \
  ((Snapshot::IsFull(kind)) ?                                                  \
  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 (Snapshot::IsFull(kind) ||
      (kind == Snapshot::kScript && !is_in_fullsnapshot)) {
    // Read in the base information.
    classid_t class_id = reader->ReadClassIDValue();

    // Allocate class object of specified kind.
    if (Snapshot::IsFull(kind)) {
      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_snapshot(kind),
                       kAsReference);
    cls.StorePointer(&cls.raw_ptr()->dependent_code_, Array::null());
    ASSERT(!cls.IsInFullSnapshot() || (Snapshot::IsFull(kind)));
  } 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 (Snapshot::IsFull(kind) ||
      (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_snapshot(kind));
  } 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 &&
      (!Snapshot::IsFull(kind) && 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 && (!Snapshot::IsFull(kind));
  reader->AddBackRef(object_id,
                     &type_arguments,
                     kIsDeserialized,
                     defer_canonicalization);

  // Set the instantiations field, which is only read from a full snapshot.
  if (Snapshot::IsFull(kind)) {
    *(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 (Snapshot::IsFull(kind)) {
    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) || (Snapshot::IsFull(kind)));
  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) || (Snapshot::IsFull(kind)));

  // 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(Snapshot::IsFull(kind));

  // 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) || (Snapshot::IsFull(kind)));

  // 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) || (Snapshot::IsFull(kind)));

  // 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) || (Snapshot::IsFull(kind)));

  // 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) || (Snapshot::IsFull(kind)));

  // 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) || (Snapshot::IsFull(kind)));

  bool is_in_fullsnapshot = reader->Read<bool>();
  if ((Snapshot::IsFull(kind)) || !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 (Snapshot::IncludesCode(kind)) {
      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<int8_t>());
      func.set_optimized_instruction_count(reader->Read<uint16_t>());
      func.set_optimized_call_site_count(reader->Read<uint16_t>());
    }
    func.set_was_compiled(false);

    // 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 (Snapshot::IncludesCode(kind)) {
      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) || (Snapshot::IsFull(kind)));
  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 (Snapshot::IsFull(kind) || !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 (Snapshot::IncludesCode(kind)) {
      // 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<int8_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 (Snapshot::IncludesCode(kind)) {
      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) || (Snapshot::IsFull(kind)));

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

  // Set all non object fields.
  if (kind == Snapshot::kAppNoJIT) {
    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.
  READ_OBJECT_FIELDS(field,
                     field.raw()->from(),
                     field.raw()->to_snapshot(kind),
                     kAsReference);
  field.StorePointer(&field.raw_ptr()->dependent_code_, Array::null());

  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) || (Snapshot::IsFull(kind)));

  // 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 (kind != Snapshot::kAppNoJIT) {
    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 (kind == Snapshot::kAppNoJIT) {
      // 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 (kind == Snapshot::kAppNoJIT) {
    writer->WriteObjectImpl(ptr()->initializer_.precompiled_, kAsReference);
  } else {
    writer->WriteObjectImpl(ptr()->initializer_.saved_value_, kAsReference);
  }
  if (kind != Snapshot::kAppNoJIT) {
    // 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) || (Snapshot::IsFull(kind)));

  // 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) || (Snapshot::IsFull(kind)));

  // 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) || (Snapshot::IsFull(kind)));

  // 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.
  intptr_t num_flds = (script.raw()->to_snapshot(kind) - 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) || (Snapshot::IsFull(kind)));

  // 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);
  visitor.VisitPointers(from(), to_snapshot(kind));
}


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 (Snapshot::IsFull(kind)) {
      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 (!Snapshot::IsFull(kind)) {
      // The cache of resolved names in library scope is not serialized.
      library.InitResolvedNamesCache(kInitialNameCacheSize);
      library.Register();
    } else {
      library.InitResolvedNamesCache(kInitialNameCacheSize, reader);
    }
    library.StorePointer(&library.raw_ptr()->exported_names_, Array::null());
    // 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((Snapshot::IsFull(kind)) || !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) || (Snapshot::IsFull(kind)));

  // 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.
  READ_OBJECT_FIELDS(prefix,
                     prefix.raw()->from(),
                     prefix.raw()->to_snapshot(kind),
                     kAsReference);
  if (kind == Snapshot::kAppNoJIT) {
    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) || (Snapshot::IsFull(kind)));

  // 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);
  visitor.VisitPointers(from(), to_snapshot(kind));
}


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) || (Snapshot::IsFull(kind)));

  // 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) || (Snapshot::IsFull(kind)));

  // 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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  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>();
  RawInstructions* instr = reinterpret_cast<RawInstructions*>(
      reader->GetInstructionsAt(text_offset) + kHeapObjectTag);
  uword entry_point = Instructions::EntryPoint(instr);

#if defined(DEBUG)
  ASSERT(instr->IsMarked());
  ASSERT(instr->IsVMHeapObject());
  uword expected_check = reader->Read<uword>();
  intptr_t instructions_size = Utils::RoundUp(instr->size_,
                                              OS::PreferredCodeAlignment());
  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(&result.raw_ptr()->active_instructions_, instr);
  result.StorePointer(&result.raw_ptr()->instructions_, instr);

  (*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());

  return result.raw();
}


void RawCode::WriteTo(SnapshotWriter* writer,
                      intptr_t object_id,
                      Snapshot::Kind kind,
                      bool as_reference) {
  ASSERT(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  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_);

  // No disabled code in precompilation.
  ASSERT(ptr()->instructions_ == ptr()->active_instructions_);

  RawInstructions* instr = ptr()->instructions_;
  int32_t text_offset = writer->GetInstructionsId(instr, this);
  writer->Write<int32_t>(text_offset);

#if defined(DEBUG)
  uword entry = ptr()->entry_point_;
  intptr_t instructions_size = Utils::RoundUp(instr->size_,
                                              OS::PreferredCodeAlignment());
  uword check = Checksum(entry, instructions_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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  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: {
#if !defined(TARGET_ARCH_DBC)
          // Read nothing. Initialize with the lazy link entry.
          uword new_entry = NativeEntry::LinkNativeCallEntry();
          result->SetRawValueAt(i, static_cast<intptr_t>(new_entry));
#else
          UNREACHABLE();  // DBC does not support lazy native call linking.
#endif
          break;
        }
        default:
          UNREACHABLE();
      }
    }
  }
  return result->raw();
}


void RawObjectPool::WriteTo(SnapshotWriter* writer,
                            intptr_t object_id,
                            Snapshot::Kind kind,
                            bool as_reference) {
  ASSERT(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));
  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 !defined(TARGET_ARCH_DBC)
          if (entry.raw_obj_ == StubCode::CallNativeCFunction_entry()->code()) {
            // Natives can run while precompiling, becoming linked and switching
            // their stub. Reset to the initial stub used for lazy-linking.
            writer->WriteObjectImpl(
                StubCode::CallBootstrapCFunction_entry()->code(), kAsReference);
            break;
          }
#endif
          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.
#if defined(TARGET_ARCH_DBC)
          UNREACHABLE();   // DBC does not support lazy native call linking.
#endif
          break;
        }
        default:
          UNREACHABLE();
      }
    }
  }
}


RawPcDescriptors* PcDescriptors::ReadFrom(SnapshotReader* reader,
                                          intptr_t object_id,
                                          intptr_t tags,
                                          Snapshot::Kind kind,
                                          bool as_reference) {
  ASSERT(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  // 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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  // 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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  // 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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  // 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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  // 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 (Snapshot::IsFull(kind)) {
      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) || (Snapshot::IsFull(kind)));

  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>());
#if defined(TAG_IC_DATA)
  result.set_tag(reader->Read<int16_t>());
#endif

  // Set all the object fields.
  READ_OBJECT_FIELDS(result,
                     result.raw()->from(),
                     result.raw()->to_snapshot(kind),
                     kAsReference);
  if (kind == Snapshot::kAppNoJIT) {
    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) || (Snapshot::IsFull(kind)));

  // 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_);
#if defined(TAG_IC_DATA)
  writer->Write<int16_t>(ptr()->tag_);
#endif

  // 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);
  visitor.VisitPointers(from(), to_snapshot(kind));
}


RawMegamorphicCache* MegamorphicCache::ReadFrom(SnapshotReader* reader,
                                                intptr_t object_id,
                                                intptr_t tags,
                                                Snapshot::Kind kind,
                                                bool as_reference) {
  ASSERT(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  // 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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  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(Snapshot::IncludesCode(kind));
  ASSERT(Snapshot::IsFull(kind));

  // 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 (Snapshot::IsFull(kind)) {
    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(reader->thread(), 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 (Snapshot::IsFull(kind)) {
    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 (Snapshot::IsFull(kind)) {
      // Set the canonical bit.
      obj.SetCanonical();
    } else {
      obj ^= obj.CheckAndCanonicalize(reader->thread(), 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 (Snapshot::IsFull(kind)) {
    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)(reader->thread(), 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 (Snapshot::IncludesCode(kind)) {
    ASSERT(Snapshot::IsFull(kind));
    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 (Snapshot::IsFull(kind)) {
    // 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 (Snapshot::IsFull(kind)) {
    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 (Snapshot::IncludesCode(kind)) {
    ASSERT(Snapshot::IncludesCode(kind));
    ASSERT(Snapshot::IsFull(kind));
    // 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 (Snapshot::IsFull(kind)) {
        array->SetCanonical();
      } else {
        *array ^= array->CheckAndCanonicalize(reader->thread(), 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 (Snapshot::IsFull(kind)) {
    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 ((Snapshot::IsFull(kind) && !Snapshot::IncludesCode(kind)) ||
      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 (Snapshot::IsFull(kind)) {
      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 ((Snapshot::IsFull(kind) && !Snapshot::IncludesCode(kind)) ||
      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 (Snapshot::IsFull(kind)) {
    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 (Snapshot::IsFull(kind)) {
    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 (Snapshot::IsFull(kind)) {
    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(),
      (Snapshot::IsFull(kind)) ? 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 (Snapshot::IsFull(kind)) {
      // Set the canonical bit.
      result.SetCanonical();
    } else {
      result ^= result.CheckAndCanonicalize(reader->thread(), 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(!Snapshot::IsFull(kind));
  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 || Snapshot::IncludesCode(kind));

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

  SendPort& result = SendPort::ZoneHandle(reader->zone());
  if (Snapshot::IncludesCode(kind)) {
    // 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 (Snapshot::IsFull(kind)) {
    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 (Snapshot::IsFull(kind)) {
    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
