// 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/snapshot.h"

#include "platform/assert.h"
#include "vm/bootstrap.h"
#include "vm/class_finalizer.h"
#include "vm/dart.h"
#include "vm/dart_entry.h"
#include "vm/exceptions.h"
#include "vm/heap.h"
#include "vm/lockers.h"
#include "vm/longjump.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/snapshot_ids.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
#include "vm/verified_memory.h"
#include "vm/version.h"

// We currently only expect the Dart mutator to read snapshots.
#define ASSERT_NO_SAFEPOINT_SCOPE()                            \
    isolate()->AssertCurrentThreadIsMutator();                 \
    ASSERT(thread()->no_safepoint_scope_depth() != 0)

namespace dart {

static const int kNumVmIsolateSnapshotReferences = 32 * KB;
static const int kNumInitialReferencesInFullSnapshot = 160 * KB;
static const int kNumInitialReferences = 64;


static bool IsSingletonClassId(intptr_t class_id) {
  // Check if this is a singleton object class which is shared by all isolates.
  return ((class_id >= kClassCid && class_id <= kUnwindErrorCid) ||
          (class_id >= kNullCid && class_id <= kVoidCid));
}


static bool IsObjectStoreClassId(intptr_t class_id) {
  // Check if this is a class which is stored in the object store.
  return (class_id == kObjectCid ||
          (class_id >= kInstanceCid && class_id <= kUserTagCid) ||
          class_id == kArrayCid || class_id == kImmutableArrayCid ||
          RawObject::IsStringClassId(class_id) ||
          RawObject::IsTypedDataClassId(class_id) ||
          RawObject::IsExternalTypedDataClassId(class_id) ||
          class_id == kNullCid);
}


static bool IsObjectStoreTypeId(intptr_t index) {
  // Check if this is a type which is stored in the object store.
  return (index >= kObjectType && index <= kArrayType);
}


static bool IsSplitClassId(intptr_t class_id) {
  // Return whether this class is serialized in two steps: first a reference,
  // with sufficient information to allocate a correctly sized object, and then
  // later inline with complete contents.
  return class_id >= kNumPredefinedCids ||
         class_id == kArrayCid ||
         class_id == kImmutableArrayCid ||
         class_id == kObjectPoolCid ||
         RawObject::IsImplicitFieldClassId(class_id);
}


static intptr_t ClassIdFromObjectId(intptr_t object_id) {
  ASSERT(object_id > kClassIdsOffset);
  intptr_t class_id = (object_id - kClassIdsOffset);
  return class_id;
}


static intptr_t ObjectIdFromClassId(intptr_t class_id) {
  ASSERT((class_id > kIllegalCid) && (class_id < kNumPredefinedCids));
  ASSERT(!(RawObject::IsImplicitFieldClassId(class_id)));
  return (class_id + kClassIdsOffset);
}


static RawType* GetType(ObjectStore* object_store, intptr_t index) {
  switch (index) {
    case kObjectType: return object_store->object_type();
    case kNullType: return object_store->null_type();
    case kFunctionType: return object_store->function_type();
    case kNumberType: return object_store->number_type();
    case kSmiType: return object_store->smi_type();
    case kMintType: return object_store->mint_type();
    case kDoubleType: return object_store->double_type();
    case kIntType: return object_store->int_type();
    case kBoolType: return object_store->bool_type();
    case kStringType: return object_store->string_type();
    case kArrayType: return object_store->array_type();
    default: break;
  }
  UNREACHABLE();
  return Type::null();
}


static intptr_t GetTypeIndex(
    ObjectStore* object_store, const RawType* raw_type) {
  ASSERT(raw_type->IsHeapObject());
  if (raw_type == object_store->object_type()) {
    return kObjectType;
  } else if (raw_type == object_store->null_type()) {
    return kNullType;
  } else if (raw_type == object_store->function_type()) {
    return kFunctionType;
  } else if (raw_type == object_store->number_type()) {
    return kNumberType;
  } else if (raw_type == object_store->smi_type()) {
    return kSmiType;
  } else if (raw_type == object_store->mint_type()) {
    return kMintType;
  } else if (raw_type == object_store->double_type()) {
    return kDoubleType;
  } else if (raw_type == object_store->int_type()) {
    return kIntType;
  } else if (raw_type == object_store->bool_type()) {
    return kBoolType;
  } else if (raw_type == object_store->string_type()) {
    return kStringType;
  } else if (raw_type == object_store->array_type()) {
    return kArrayType;
  }
  return kInvalidIndex;
}


// TODO(5411462): Temporary setup of snapshot for testing purposes,
// the actual creation of a snapshot maybe done differently.
const Snapshot* Snapshot::SetupFromBuffer(const void* raw_memory) {
  ASSERT(raw_memory != NULL);
  ASSERT(kHeaderSize == sizeof(Snapshot));
  ASSERT(kLengthIndex == length_offset());
  ASSERT((kSnapshotFlagIndex * sizeof(int64_t)) == kind_offset());
  ASSERT((kHeapObjectTag & kInlined));
  // The kWatchedBit and kMarkBit are only set during GC operations. This
  // allows the two low bits in the header to be used for snapshotting.
  ASSERT(kObjectId ==
         ((1 << RawObject::kWatchedBit) | (1 << RawObject::kMarkBit)));
  ASSERT((kObjectAlignmentMask & kObjectId) == kObjectId);
  const Snapshot* snapshot = reinterpret_cast<const Snapshot*>(raw_memory);
  // If the raw length is negative or greater than what the local machine can
  // handle, then signal an error.
  int64_t snapshot_length = ReadUnaligned(&snapshot->unaligned_length_);
  if ((snapshot_length < 0) || (snapshot_length > kIntptrMax)) {
    return NULL;
  }
  return snapshot;
}


RawSmi* BaseReader::ReadAsSmi() {
  intptr_t value = Read<int32_t>();
  ASSERT((value & kSmiTagMask) == kSmiTag);
  return reinterpret_cast<RawSmi*>(value);
}


intptr_t BaseReader::ReadSmiValue() {
  return Smi::Value(ReadAsSmi());
}


SnapshotReader::SnapshotReader(
    const uint8_t* buffer,
    intptr_t size,
    const uint8_t* instructions_buffer,
    const uint8_t* data_buffer,
    Snapshot::Kind kind,
    ZoneGrowableArray<BackRefNode>* backward_refs,
    Thread* thread)
    : BaseReader(buffer, size),
      instructions_buffer_(instructions_buffer),
      data_buffer_(data_buffer),
      kind_(kind),
      thread_(thread),
      zone_(thread->zone()),
      heap_(isolate()->heap()),
      old_space_(thread_->isolate()->heap()->old_space()),
      cls_(Class::Handle(zone_)),
      obj_(Object::Handle(zone_)),
      pobj_(PassiveObject::Handle(zone_)),
      array_(Array::Handle(zone_)),
      field_(Field::Handle(zone_)),
      str_(String::Handle(zone_)),
      library_(Library::Handle(zone_)),
      type_(AbstractType::Handle(zone_)),
      type_arguments_(TypeArguments::Handle(zone_)),
      tokens_(GrowableObjectArray::Handle(zone_)),
      stream_(TokenStream::Handle(zone_)),
      data_(ExternalTypedData::Handle(zone_)),
      typed_data_(TypedData::Handle(zone_)),
      code_(Code::Handle(zone_)),
      function_(Function::Handle(zone_)),
      megamorphic_cache_(MegamorphicCache::Handle(zone_)),
      error_(UnhandledException::Handle(zone_)),
      max_vm_isolate_object_id_(
          (Snapshot::IsFull(kind)) ?
              Object::vm_isolate_snapshot_object_table().Length() : 0),
      backward_references_(backward_refs),
      instructions_reader_(NULL) {
  if (instructions_buffer != NULL) {
    instructions_reader_ =
        new InstructionsReader(instructions_buffer, data_buffer);
  }
}


RawObject* SnapshotReader::ReadObject() {
  // Setup for long jump in case there is an exception while reading.
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    PassiveObject& obj =
        PassiveObject::Handle(zone(), ReadObjectImpl(kAsInlinedObject));
    for (intptr_t i = 0; i < backward_references_->length(); i++) {
      if (!(*backward_references_)[i].is_deserialized()) {
        ReadObjectImpl(kAsInlinedObject);
        (*backward_references_)[i].set_state(kIsDeserialized);
      }
    }
    if (!Snapshot::IsFull(kind())) {
      ProcessDeferredCanonicalizations();
    }
    return obj.raw();
  } else {
    // An error occurred while reading, return the error object.
    const Error& err = Error::Handle(thread()->sticky_error());
    thread()->clear_sticky_error();
    return err.raw();
  }
}


RawClass* SnapshotReader::ReadClassId(intptr_t object_id) {
  ASSERT(!Snapshot::IsFull(kind_));
  // Read the class header information and lookup the class.
  intptr_t class_header = Read<int32_t>();
  ASSERT((class_header & kSmiTagMask) != kSmiTag);
  ASSERT(!IsVMIsolateObject(class_header) ||
         !IsSingletonClassId(GetVMIsolateObjectId(class_header)));
  ASSERT((SerializedHeaderTag::decode(class_header) != kObjectId) ||
         !IsObjectStoreClassId(SerializedHeaderData::decode(class_header)));
  Class& cls = Class::ZoneHandle(zone(), Class::null());
  AddBackRef(object_id, &cls, kIsDeserialized);
  // Read the library/class information and lookup the class.
  str_ ^= ReadObjectImpl(class_header, kAsInlinedObject, kInvalidPatchIndex, 0);
  library_ = Library::LookupLibrary(str_);
  if (library_.IsNull() || !library_.Loaded()) {
    SetReadException("Invalid object found in message.");
  }
  str_ ^= ReadObjectImpl(kAsInlinedObject);
  cls = library_.LookupClass(str_);
  if (cls.IsNull()) {
    SetReadException("Invalid object found in message.");
  }
  cls.EnsureIsFinalized(thread());
  return cls.raw();
}


RawFunction* SnapshotReader::ReadFunctionId(intptr_t object_id) {
  ASSERT(kind_ == Snapshot::kScript);
  // Read the function header information and lookup the function.
  intptr_t func_header = Read<int32_t>();
  ASSERT((func_header & kSmiTagMask) != kSmiTag);
  ASSERT(!IsVMIsolateObject(func_header) ||
         !IsSingletonClassId(GetVMIsolateObjectId(func_header)));
  ASSERT((SerializedHeaderTag::decode(func_header) != kObjectId) ||
         !IsObjectStoreClassId(SerializedHeaderData::decode(func_header)));
  Function& func = Function::ZoneHandle(zone(), Function::null());
  AddBackRef(object_id, &func, kIsDeserialized);
  // Read the library/class/function information and lookup the function.
  str_ ^= ReadObjectImpl(func_header, kAsInlinedObject, kInvalidPatchIndex, 0);
  library_ = Library::LookupLibrary(str_);
  if (library_.IsNull() || !library_.Loaded()) {
    SetReadException("Expected a library name, but found an invalid name.");
  }
  str_ ^= ReadObjectImpl(kAsInlinedObject);
  if (str_.Equals(Symbols::TopLevel(), 0, Symbols::TopLevel().Length())) {
    str_ ^= ReadObjectImpl(kAsInlinedObject);
    func ^= library_.LookupLocalFunction(str_);
  } else {
    cls_ = library_.LookupClass(str_);
    if (cls_.IsNull()) {
      SetReadException("Expected a class name, but found an invalid name.");
    }
    cls_.EnsureIsFinalized(thread());
    str_ ^= ReadObjectImpl(kAsInlinedObject);
    func ^= cls_.LookupFunctionAllowPrivate(str_);
  }
  if (func.IsNull()) {
    SetReadException("Expected a function name, but found an invalid name.");
  }
  return func.raw();
}


RawObject* SnapshotReader::ReadStaticImplicitClosure(intptr_t object_id,
                                                     intptr_t class_header) {
  ASSERT(!Snapshot::IsFull(kind_));

  // First create a function object and associate it with the specified
  // 'object_id'.
  Function& func = Function::Handle(zone(), Function::null());
  Instance& obj = Instance::ZoneHandle(zone(), Instance::null());
  AddBackRef(object_id, &obj, kIsDeserialized);

  // Read the library/class/function information and lookup the function.
  str_ ^= ReadObjectImpl(kAsInlinedObject);
  library_ = Library::LookupLibrary(str_);
  if (library_.IsNull() || !library_.Loaded()) {
    SetReadException("Invalid Library object found in message.");
  }
  str_ ^= ReadObjectImpl(kAsInlinedObject);
  if (str_.Equals(Symbols::TopLevel())) {
    str_ ^= ReadObjectImpl(kAsInlinedObject);
    func = library_.LookupFunctionAllowPrivate(str_);
  } else {
    cls_ = library_.LookupClassAllowPrivate(str_);
    if (cls_.IsNull()) {
      OS::Print("Name of class not found %s\n", str_.ToCString());
      SetReadException("Invalid Class object found in message.");
    }
    cls_.EnsureIsFinalized(thread());
    str_ ^= ReadObjectImpl(kAsInlinedObject);
    func = cls_.LookupFunctionAllowPrivate(str_);
  }
  if (func.IsNull()) {
    SetReadException("Invalid function object found in message.");
  }
  func = func.ImplicitClosureFunction();
  ASSERT(!func.IsNull());

  // Return the associated implicit static closure.
  obj = func.ImplicitStaticClosure();
  return obj.raw();
}


intptr_t SnapshotReader::NextAvailableObjectId() const {
  return backward_references_->length() +
      kMaxPredefinedObjectIds + max_vm_isolate_object_id_;
}


void SnapshotReader::SetReadException(const char* msg) {
  const String& error_str = String::Handle(zone(), String::New(msg));
  const Array& args = Array::Handle(zone(), Array::New(1));
  args.SetAt(0, error_str);
  Object& result = Object::Handle(zone());
  const Library& library = Library::Handle(zone(), Library::CoreLibrary());
  result = DartLibraryCalls::InstanceCreate(library,
                                            Symbols::ArgumentError(),
                                            Symbols::Dot(),
                                            args);
  const Stacktrace& stacktrace = Stacktrace::Handle(zone());
  const UnhandledException& error = UnhandledException::Handle(
      zone(), UnhandledException::New(Instance::Cast(result), stacktrace));
  thread()->long_jump_base()->Jump(1, error);
}


RawObject* SnapshotReader::VmIsolateSnapshotObject(intptr_t index) const {
  return Object::vm_isolate_snapshot_object_table().At(index);
}


bool SnapshotReader::is_vm_isolate() const {
  return isolate() == Dart::vm_isolate();
}


RawObject* SnapshotReader::ReadObjectImpl(bool as_reference,
                                          intptr_t patch_object_id,
                                          intptr_t patch_offset) {
  int64_t header_value = Read<int64_t>();
  if ((header_value & kSmiTagMask) == kSmiTag) {
    return NewInteger(header_value);
  }
  ASSERT((header_value <= kIntptrMax) && (header_value >= kIntptrMin));
  return ReadObjectImpl(static_cast<intptr_t>(header_value),
                        as_reference,
                        patch_object_id,
                        patch_offset);
}


RawObject* SnapshotReader::ReadObjectImpl(intptr_t header_value,
                                          bool as_reference,
                                          intptr_t patch_object_id,
                                          intptr_t patch_offset) {
  if (IsVMIsolateObject(header_value)) {
    return ReadVMIsolateObject(header_value);
  }
  if (SerializedHeaderTag::decode(header_value) == kObjectId) {
    return ReadIndexedObject(SerializedHeaderData::decode(header_value),
                             patch_object_id,
                             patch_offset);
  }
  ASSERT(SerializedHeaderTag::decode(header_value) == kInlined);
  intptr_t object_id = SerializedHeaderData::decode(header_value);
  if (object_id == kOmittedObjectId) {
    object_id = NextAvailableObjectId();
  }

  // Read the class header information.
  intptr_t class_header = Read<int32_t>();
  intptr_t tags = ReadTags();
  bool read_as_reference = as_reference && !RawObject::IsCanonical(tags);
  intptr_t header_id = SerializedHeaderData::decode(class_header);
  if (header_id == kInstanceObjectId) {
    return ReadInstance(object_id, tags, read_as_reference);
  } else if (header_id == kStaticImplicitClosureObjectId) {
    // We skip the tags that have been written as the implicit static
    // closure is going to be created in this isolate or the canonical
    // version already created in the isolate will be used.
    return ReadStaticImplicitClosure(object_id, class_header);
  }
  ASSERT((class_header & kSmiTagMask) != kSmiTag);

  intptr_t class_id = LookupInternalClass(class_header);
  switch (class_id) {
#define SNAPSHOT_READ(clazz)                                                   \
    case clazz::kClassId: {                                                    \
      pobj_ = clazz::ReadFrom(this, object_id, tags, kind_, read_as_reference);\
      break;                                                                   \
    }
    CLASS_LIST_NO_OBJECT(SNAPSHOT_READ)
#undef SNAPSHOT_READ
#define SNAPSHOT_READ(clazz)                                                   \
        case kTypedData##clazz##Cid:                                           \

    CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
      tags = RawObject::ClassIdTag::update(class_id, tags);
      pobj_ = TypedData::ReadFrom(
          this, object_id, tags, kind_, read_as_reference);
      break;
    }
#undef SNAPSHOT_READ
#define SNAPSHOT_READ(clazz)                                                   \
    case kExternalTypedData##clazz##Cid:                                       \

    CLASS_LIST_TYPED_DATA(SNAPSHOT_READ) {
      tags = RawObject::ClassIdTag::update(class_id, tags);
      pobj_ = ExternalTypedData::ReadFrom(this, object_id, tags, kind_, true);
      break;
    }
#undef SNAPSHOT_READ
    default: UNREACHABLE(); break;
  }
  if (!read_as_reference) {
    AddPatchRecord(object_id, patch_object_id, patch_offset);
  }
  return pobj_.raw();
}


RawObject* SnapshotReader::ReadInstance(intptr_t object_id,
                                        intptr_t tags,
                                        bool as_reference) {
  // Object is regular dart instance.
  intptr_t instance_size = 0;
  Instance* result = NULL;
  DeserializeState state;
  if (!as_reference) {
    result = reinterpret_cast<Instance*>(GetBackRef(object_id));
    state = kIsDeserialized;
  } else {
    state = kIsNotDeserialized;
  }
  if (result == NULL) {
    result = &(Instance::ZoneHandle(zone(), Instance::null()));
    AddBackRef(object_id, result, state);
    cls_ ^= ReadObjectImpl(kAsInlinedObject);
    ASSERT(!cls_.IsNull());
    // Closure instances are handled by Closure::ReadFrom().
    ASSERT(!cls_.IsClosureClass());
    instance_size = cls_.instance_size();
    ASSERT(instance_size > 0);
    // Allocate the instance and read in all the fields for the object.
    if (Snapshot::IsFull(kind_)) {
      *result ^= AllocateUninitialized(cls_.id(), instance_size);
    } else {
      *result ^= Object::Allocate(cls_.id(), instance_size, HEAP_SPACE(kind_));
    }
  } else {
    cls_ ^= ReadObjectImpl(kAsInlinedObject);
    ASSERT(!cls_.IsNull());
    instance_size = cls_.instance_size();
  }
  if (!as_reference) {
    // Read all the individual fields for inlined objects.
    intptr_t next_field_offset = cls_.next_field_offset();

    intptr_t type_argument_field_offset = cls_.type_arguments_field_offset();
    ASSERT(next_field_offset > 0);
    // Instance::NextFieldOffset() returns the offset of the first field in
    // a Dart object.
    bool read_as_reference = RawObject::IsCanonical(tags) ? false : true;
    intptr_t offset = Instance::NextFieldOffset();
    intptr_t result_cid = result->GetClassId();
    while (offset < next_field_offset) {
      pobj_ = ReadObjectImpl(read_as_reference);
      result->SetFieldAtOffset(offset, pobj_);
      if ((offset != type_argument_field_offset) &&
          (kind_ == Snapshot::kMessage) &&
          FLAG_use_field_guards) {
        // TODO(fschneider): Consider hoisting these lookups out of the loop.
        // This would involve creating a handle, since cls_ can't be reused
        // across the call to ReadObjectImpl.
        cls_ = isolate()->class_table()->At(result_cid);
        array_ = cls_.OffsetToFieldMap();
        field_ ^= array_.At(offset >> kWordSizeLog2);
        ASSERT(!field_.IsNull());
        ASSERT(field_.Offset() == offset);
        obj_ = pobj_.raw();
        field_.RecordStore(obj_);
      }
      // TODO(fschneider): Verify the guarded cid and length for other kinds of
      // snapshot (kFull, kScript) with asserts.
      offset += kWordSize;
    }
    if (Snapshot::IsFull(kind_)) {
      // We create an uninitialized object in the case of full snapshots, so
      // we need to initialize any remaining padding area with the Null object.
      while (offset < instance_size) {
        result->SetFieldAtOffset(offset, Object::null_object());
        offset += kWordSize;
      }
    }
    if (RawObject::IsCanonical(tags)) {
      if (Snapshot::IsFull(kind_)) {
        result->SetCanonical();
      } else {
        *result = result->CheckAndCanonicalize(thread(), NULL);
        ASSERT(!result->IsNull());
      }
    }
  }
  return result->raw();
}


void SnapshotReader::AddBackRef(intptr_t id,
                                Object* obj,
                                DeserializeState state,
                                bool defer_canonicalization) {
  intptr_t index = (id - kMaxPredefinedObjectIds);
  ASSERT(index >= max_vm_isolate_object_id_);
  index -= max_vm_isolate_object_id_;
  ASSERT(index == backward_references_->length());
  BackRefNode node(obj, state, defer_canonicalization);
  backward_references_->Add(node);
}


Object* SnapshotReader::GetBackRef(intptr_t id) {
  ASSERT(id >= kMaxPredefinedObjectIds);
  intptr_t index = (id - kMaxPredefinedObjectIds);
  ASSERT(index >= max_vm_isolate_object_id_);
  index -= max_vm_isolate_object_id_;
  if (index < backward_references_->length()) {
    return (*backward_references_)[index].reference();
  }
  return NULL;
}


class HeapLocker : public StackResource {
 public:
  HeapLocker(Thread* thread, PageSpace* page_space)
      : StackResource(thread), page_space_(page_space) {
        page_space_->AcquireDataLock();
  }
  ~HeapLocker() {
    page_space_->ReleaseDataLock();
  }

 private:
  PageSpace* page_space_;
};


RawApiError* SnapshotReader::ReadFullSnapshot() {
  ASSERT(Snapshot::IsFull(kind_));
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  ASSERT(isolate != NULL);
  ObjectStore* object_store = isolate->object_store();
  ASSERT(object_store != NULL);

  // First read the version string, and check that it matches.
  RawApiError* error = VerifyVersion();
  if (error != ApiError::null()) {
    return error;
  }

  // The version string matches. Read the rest of the snapshot.

  // TODO(asiva): Add a check here to ensure we have the right heap
  // size for the full snapshot being read.
  {
    NoSafepointScope no_safepoint;
    HeapLocker hl(thread, old_space());

    // Read in all the objects stored in the object store.
    intptr_t num_flds =
        (object_store->to_snapshot(kind_) - object_store->from());
    for (intptr_t i = 0; i <= num_flds; i++) {
      *(object_store->from() + i) = ReadObjectImpl(kAsInlinedObject);
    }
    for (intptr_t i = 0; i < backward_references_->length(); i++) {
      if (!(*backward_references_)[i].is_deserialized()) {
        ReadObjectImpl(kAsInlinedObject);
        (*backward_references_)[i].set_state(kIsDeserialized);
      }
    }

    if (Snapshot::IncludesCode(kind_)) {
      ICData& ic = ICData::Handle(thread->zone());
      Object& funcOrCode = Object::Handle(thread->zone());
      Code& code = Code::Handle(thread->zone());
      Smi& entry_point = Smi::Handle(thread->zone());
      for (intptr_t i = 0; i < backward_references_->length(); i++) {
        if ((*backward_references_)[i].reference()->IsICData()) {
          ic ^= (*backward_references_)[i].reference()->raw();
          for (intptr_t j = 0; j < ic.NumberOfChecks(); j++) {
            funcOrCode = ic.GetTargetOrCodeAt(j);
            if (funcOrCode.IsCode()) {
              code ^= funcOrCode.raw();
              entry_point = Smi::FromAlignedAddress(code.EntryPoint());
              ic.SetEntryPointAt(j, entry_point);
            }
          }
        }
      }
    }

    // Validate the class table.
#if defined(DEBUG)
    isolate->ValidateClassTable();
#endif

    // Setup native resolver for bootstrap impl.
    Bootstrap::SetupNativeResolver();
  }

  Class& cls = Class::Handle(thread->zone());
  for (intptr_t i = 0; i < backward_references_->length(); i++) {
    if ((*backward_references_)[i].reference()->IsClass()) {
      cls ^= (*backward_references_)[i].reference()->raw();
      cls.RehashConstants(thread->zone());
    }
  }

  return ApiError::null();
}


RawObject* SnapshotReader::ReadScriptSnapshot() {
  ASSERT(kind_ == Snapshot::kScript);

  // First read the version string, and check that it matches.
  RawApiError* error = VerifyVersion();
  if (error != ApiError::null()) {
    return error;
  }

  // The version string matches. Read the rest of the snapshot.
  obj_ = ReadObject();
  if (!obj_.IsLibrary()) {
    if (!obj_.IsError()) {
      const intptr_t kMessageBufferSize = 128;
      char message_buffer[kMessageBufferSize];
      OS::SNPrint(message_buffer,
                  kMessageBufferSize,
                  "Invalid object %s found in script snapshot",
                  obj_.ToCString());
      const String& msg = String::Handle(String::New(message_buffer));
      obj_ = ApiError::New(msg);
    }
  }
  return obj_.raw();
}


RawApiError* SnapshotReader::VerifyVersion() {
  // If the version string doesn't match, return an error.
  // Note: New things are allocated only if we're going to return an error.

  const char* expected_version = Version::SnapshotString();
  ASSERT(expected_version != NULL);
  const intptr_t version_len = strlen(expected_version);
  if (PendingBytes() < version_len) {
    const intptr_t kMessageBufferSize = 128;
    char message_buffer[kMessageBufferSize];
    OS::SNPrint(message_buffer,
                kMessageBufferSize,
                "No full snapshot version found, expected '%s'",
                Version::SnapshotString());
    // This can also fail while bringing up the VM isolate, so make sure to
    // allocate the error message in old space.
    const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
    return ApiError::New(msg, Heap::kOld);
  }

  const char* version = reinterpret_cast<const char*>(CurrentBufferAddress());
  ASSERT(version != NULL);
  if (strncmp(version, expected_version, version_len)) {
    const intptr_t kMessageBufferSize = 256;
    char message_buffer[kMessageBufferSize];
    char* actual_version = OS::StrNDup(version, version_len);
    OS::SNPrint(message_buffer,
                kMessageBufferSize,
                "Wrong %s snapshot version, expected '%s' found '%s'",
                (Snapshot::IsFull(kind_)) ? "full" : "script",
                Version::SnapshotString(),
                actual_version);
    free(actual_version);
    // This can also fail while bringing up the VM isolate, so make sure to
    // allocate the error message in old space.
    const String& msg = String::Handle(String::New(message_buffer, Heap::kOld));
    return ApiError::New(msg, Heap::kOld);
  }
  Advance(version_len);
  return ApiError::null();
}


#define ALLOC_NEW_OBJECT_WITH_LEN(type, length)                                \
  ASSERT(Snapshot::IsFull(kind_));                                            \
  ASSERT_NO_SAFEPOINT_SCOPE();                                                 \
  Raw##type* obj = reinterpret_cast<Raw##type*>(                               \
      AllocateUninitialized(k##type##Cid, type::InstanceSize(length)));        \
  obj->StoreSmi(&(obj->ptr()->length_), Smi::New(length));                     \
  return obj;                                                                  \


RawArray* SnapshotReader::NewArray(intptr_t len) {
  ALLOC_NEW_OBJECT_WITH_LEN(Array, len);
}


RawImmutableArray* SnapshotReader::NewImmutableArray(intptr_t len) {
  ALLOC_NEW_OBJECT_WITH_LEN(ImmutableArray, len);
}


RawOneByteString* SnapshotReader::NewOneByteString(intptr_t len) {
  ALLOC_NEW_OBJECT_WITH_LEN(OneByteString, len);
}


RawTwoByteString* SnapshotReader::NewTwoByteString(intptr_t len) {
  ALLOC_NEW_OBJECT_WITH_LEN(TwoByteString, len);
}


RawTypeArguments* SnapshotReader::NewTypeArguments(intptr_t len) {
  ALLOC_NEW_OBJECT_WITH_LEN(TypeArguments, len);
}


RawObjectPool* SnapshotReader::NewObjectPool(intptr_t len) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawObjectPool* obj = reinterpret_cast<RawObjectPool*>(
      AllocateUninitialized(kObjectPoolCid, ObjectPool::InstanceSize(len)));
  obj->ptr()->length_ = len;
  return obj;
}


RawLocalVarDescriptors* SnapshotReader::NewLocalVarDescriptors(
    intptr_t num_entries) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawLocalVarDescriptors* obj = reinterpret_cast<RawLocalVarDescriptors*>(
      AllocateUninitialized(kLocalVarDescriptorsCid,
                            LocalVarDescriptors::InstanceSize(num_entries)));
  obj->ptr()->num_entries_ = num_entries;
  return obj;
}


RawExceptionHandlers* SnapshotReader::NewExceptionHandlers(
    intptr_t num_entries) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawExceptionHandlers* obj = reinterpret_cast<RawExceptionHandlers*>(
      AllocateUninitialized(kExceptionHandlersCid,
                            ExceptionHandlers::InstanceSize(num_entries)));
  obj->ptr()->num_entries_ = num_entries;
  return obj;
}


RawPcDescriptors* SnapshotReader::NewPcDescriptors(intptr_t len) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawPcDescriptors* obj = reinterpret_cast<RawPcDescriptors*>(
      AllocateUninitialized(kPcDescriptorsCid,
                            PcDescriptors::InstanceSize(len)));
  obj->ptr()->length_ = len;
  return obj;
}


RawCodeSourceMap* SnapshotReader::NewCodeSourceMap(intptr_t len) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawCodeSourceMap* obj = reinterpret_cast<RawCodeSourceMap*>(
      AllocateUninitialized(kCodeSourceMapCid,
                            CodeSourceMap::InstanceSize(len)));
  obj->ptr()->length_ = len;
  return obj;
}


RawStackmap* SnapshotReader::NewStackmap(intptr_t len) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawStackmap* obj = reinterpret_cast<RawStackmap*>(
      AllocateUninitialized(kStackmapCid, Stackmap::InstanceSize(len)));
  obj->ptr()->length_ = len;
  return obj;
}


RawContextScope* SnapshotReader::NewContextScope(intptr_t num_variables) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawContextScope* obj = reinterpret_cast<RawContextScope*>(
      AllocateUninitialized(kContextScopeCid,
                            ContextScope::InstanceSize(num_variables)));
  obj->ptr()->num_variables_ = num_variables;
  return obj;
}


RawCode* SnapshotReader::NewCode(intptr_t pointer_offsets_length) {
  ASSERT(pointer_offsets_length == 0);
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawCode* obj = reinterpret_cast<RawCode*>(
      AllocateUninitialized(kCodeCid, Code::InstanceSize(0)));
  return obj;
}


RawTokenStream* SnapshotReader::NewTokenStream(intptr_t len) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  stream_ = reinterpret_cast<RawTokenStream*>(
      AllocateUninitialized(kTokenStreamCid, TokenStream::InstanceSize()));
  uint8_t* array = const_cast<uint8_t*>(CurrentBufferAddress());
  ASSERT(array != NULL);
  Advance(len);
  data_ = reinterpret_cast<RawExternalTypedData*>(
      AllocateUninitialized(kExternalTypedDataUint8ArrayCid,
                            ExternalTypedData::InstanceSize()));
  data_.SetData(array);
  data_.SetLength(len);
  stream_.SetStream(data_);
  return stream_.raw();
}


RawContext* SnapshotReader::NewContext(intptr_t num_variables) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawContext* obj = reinterpret_cast<RawContext*>(
      AllocateUninitialized(kContextCid, Context::InstanceSize(num_variables)));
  obj->ptr()->num_variables_ = num_variables;
  return obj;
}


RawClass* SnapshotReader::NewClass(intptr_t class_id) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  if (class_id < kNumPredefinedCids) {
    ASSERT((class_id >= kInstanceCid) &&
           (class_id <= kNullCid));
    return isolate()->class_table()->At(class_id);
  }
  RawClass* obj = reinterpret_cast<RawClass*>(
      AllocateUninitialized(kClassCid, Class::InstanceSize()));
  Instance fake;
  obj->ptr()->handle_vtable_ = fake.vtable();
  cls_ = obj;
  cls_.set_id(class_id);
  isolate()->RegisterClassAt(class_id, cls_);
  return cls_.raw();
}


RawInstance* SnapshotReader::NewInstance() {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawInstance* obj = reinterpret_cast<RawInstance*>(
      AllocateUninitialized(kInstanceCid, Instance::InstanceSize()));
  return obj;
}


RawMint* SnapshotReader::NewMint(int64_t value) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawMint* obj = reinterpret_cast<RawMint*>(
      AllocateUninitialized(kMintCid, Mint::InstanceSize()));
  obj->ptr()->value_ = value;
  return obj;
}


RawDouble* SnapshotReader::NewDouble(double value) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawDouble* obj = reinterpret_cast<RawDouble*>(
      AllocateUninitialized(kDoubleCid, Double::InstanceSize()));
  obj->ptr()->value_ = value;
  return obj;
}


RawTypedData* SnapshotReader::NewTypedData(intptr_t class_id, intptr_t len) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  const intptr_t lengthInBytes = len * TypedData::ElementSizeInBytes(class_id);
  RawTypedData* obj = reinterpret_cast<RawTypedData*>(
      AllocateUninitialized(class_id, TypedData::InstanceSize(lengthInBytes)));
  obj->StoreSmi(&(obj->ptr()->length_), Smi::New(len));
  return obj;
}


#define ALLOC_NEW_OBJECT(type)                                                 \
  ASSERT(Snapshot::IsFull(kind_));                                            \
  ASSERT_NO_SAFEPOINT_SCOPE();                                                 \
  return reinterpret_cast<Raw##type*>(                                         \
      AllocateUninitialized(k##type##Cid, type::InstanceSize()));              \


RawBigint* SnapshotReader::NewBigint() {
  ALLOC_NEW_OBJECT(Bigint);
}


RawUnresolvedClass* SnapshotReader::NewUnresolvedClass() {
  ALLOC_NEW_OBJECT(UnresolvedClass);
}


RawType* SnapshotReader::NewType() {
  ALLOC_NEW_OBJECT(Type);
}


RawTypeRef* SnapshotReader::NewTypeRef() {
  ALLOC_NEW_OBJECT(TypeRef);
}


RawTypeParameter* SnapshotReader::NewTypeParameter() {
  ALLOC_NEW_OBJECT(TypeParameter);
}


RawBoundedType* SnapshotReader::NewBoundedType() {
  ALLOC_NEW_OBJECT(BoundedType);
}


RawMixinAppType* SnapshotReader::NewMixinAppType() {
  ALLOC_NEW_OBJECT(MixinAppType);
}


RawPatchClass* SnapshotReader::NewPatchClass() {
  ALLOC_NEW_OBJECT(PatchClass);
}


RawClosure* SnapshotReader::NewClosure() {
  ALLOC_NEW_OBJECT(Closure);
}


RawClosureData* SnapshotReader::NewClosureData() {
  ALLOC_NEW_OBJECT(ClosureData);
}


RawRedirectionData* SnapshotReader::NewRedirectionData() {
  ALLOC_NEW_OBJECT(RedirectionData);
}


RawFunction* SnapshotReader::NewFunction() {
  ALLOC_NEW_OBJECT(Function);
}


RawICData* SnapshotReader::NewICData() {
  ALLOC_NEW_OBJECT(ICData);
}


RawLinkedHashMap* SnapshotReader::NewLinkedHashMap() {
  ALLOC_NEW_OBJECT(LinkedHashMap);
}


RawMegamorphicCache* SnapshotReader::NewMegamorphicCache() {
  ALLOC_NEW_OBJECT(MegamorphicCache);
}


RawSubtypeTestCache* SnapshotReader::NewSubtypeTestCache() {
  ALLOC_NEW_OBJECT(SubtypeTestCache);
}


RawField* SnapshotReader::NewField() {
  ALLOC_NEW_OBJECT(Field);
}


RawLibrary* SnapshotReader::NewLibrary() {
  ALLOC_NEW_OBJECT(Library);
}


RawLibraryPrefix* SnapshotReader::NewLibraryPrefix() {
  ALLOC_NEW_OBJECT(LibraryPrefix);
}


RawNamespace* SnapshotReader::NewNamespace() {
  ALLOC_NEW_OBJECT(Namespace);
}


RawScript* SnapshotReader::NewScript() {
  ALLOC_NEW_OBJECT(Script);
}


RawLiteralToken* SnapshotReader::NewLiteralToken() {
  ALLOC_NEW_OBJECT(LiteralToken);
}


RawGrowableObjectArray* SnapshotReader::NewGrowableObjectArray() {
  ALLOC_NEW_OBJECT(GrowableObjectArray);
}


RawWeakProperty* SnapshotReader::NewWeakProperty() {
  ALLOC_NEW_OBJECT(WeakProperty);
}


RawRegExp* SnapshotReader::NewRegExp() {
  ALLOC_NEW_OBJECT(RegExp);
}


RawFloat32x4* SnapshotReader::NewFloat32x4(float v0, float v1, float v2,
                                           float v3) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawFloat32x4* obj = reinterpret_cast<RawFloat32x4*>(
      AllocateUninitialized(kFloat32x4Cid, Float32x4::InstanceSize()));
  obj->ptr()->value_[0] = v0;
  obj->ptr()->value_[1] = v1;
  obj->ptr()->value_[2] = v2;
  obj->ptr()->value_[3] = v3;
  return obj;
}


RawInt32x4* SnapshotReader::NewInt32x4(uint32_t v0, uint32_t v1, uint32_t v2,
                                       uint32_t v3) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawInt32x4* obj = reinterpret_cast<RawInt32x4*>(
      AllocateUninitialized(kInt32x4Cid, Int32x4::InstanceSize()));
  obj->ptr()->value_[0] = v0;
  obj->ptr()->value_[1] = v1;
  obj->ptr()->value_[2] = v2;
  obj->ptr()->value_[3] = v3;
  return obj;
}


RawFloat64x2* SnapshotReader::NewFloat64x2(double v0, double v1) {
  ASSERT(Snapshot::IsFull(kind_));
  ASSERT_NO_SAFEPOINT_SCOPE();
  RawFloat64x2* obj = reinterpret_cast<RawFloat64x2*>(
      AllocateUninitialized(kFloat64x2Cid, Float64x2::InstanceSize()));
  obj->ptr()->value_[0] = v0;
  obj->ptr()->value_[1] = v1;
  return obj;
}


RawApiError* SnapshotReader::NewApiError() {
  ALLOC_NEW_OBJECT(ApiError);
}


RawLanguageError* SnapshotReader::NewLanguageError() {
  ALLOC_NEW_OBJECT(LanguageError);
}


RawUnhandledException* SnapshotReader::NewUnhandledException() {
  ALLOC_NEW_OBJECT(UnhandledException);
}


RawObject* SnapshotReader::NewInteger(int64_t value) {
  ASSERT((value & kSmiTagMask) == kSmiTag);
  value = value >> kSmiTagShift;
  if (Smi::IsValid(value)) {
    return Smi::New(static_cast<intptr_t>(value));
  }
  if (Snapshot::IsFull(kind_)) {
    return NewMint(value);
  }
  return Mint::NewCanonical(value);
}


RawStacktrace* SnapshotReader::NewStacktrace() {
  ALLOC_NEW_OBJECT(Stacktrace);
}


int32_t InstructionsWriter::GetOffsetFor(RawInstructions* instructions,
                                         RawCode* code) {
#if defined(PRODUCT)
  // Instructions are only dedup in product mode because it obfuscates profiler
  // results.
  for (intptr_t i = 0; i < instructions_.length(); i++) {
    if (instructions_[i].raw_insns_ == instructions) {
      return instructions_[i].offset_;
    }
  }
#endif

  intptr_t heap_size = instructions->Size();
  intptr_t offset = next_offset_;
  next_offset_ += heap_size;
  instructions_.Add(InstructionsData(instructions, code, offset));

  return offset;
}


int32_t InstructionsWriter::GetObjectOffsetFor(RawObject* raw_object) {
  intptr_t heap_size = raw_object->Size();
  intptr_t offset = next_object_offset_;
  next_object_offset_ += heap_size;
  objects_.Add(ObjectData(raw_object));
  return offset;
}


static void EnsureIdentifier(char* label) {
  for (char c = *label; c != '\0'; c = *++label) {
    if (((c >= 'a') && (c <= 'z')) ||
        ((c >= 'A') && (c <= 'Z')) ||
        ((c >= '0') && (c <= '9'))) {
      continue;
    }
    *label = '_';
  }
}


void AssemblyInstructionsWriter::Write() {
  Zone* zone = Thread::Current()->zone();

  // Handlify collected raw pointers as building the names below
  // will allocate on the Dart heap.
  for (intptr_t i = 0; i < instructions_.length(); i++) {
    InstructionsData& data = instructions_[i];
    data.insns_ = &Instructions::Handle(zone, data.raw_insns_);
    ASSERT(data.raw_code_ != NULL);
    data.code_ = &Code::Handle(zone, data.raw_code_);
  }
  for (intptr_t i = 0; i < objects_.length(); i++) {
    ObjectData& data = objects_[i];
    data.obj_ = &Object::Handle(zone, data.raw_obj_);
  }

  assembly_stream_.Print(".text\n");
  assembly_stream_.Print(".globl _kInstructionsSnapshot\n");
  // Start snapshot at page boundary.
  ASSERT(VirtualMemory::PageSize() >= OS::kMaxPreferredCodeAlignment);
  assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
  assembly_stream_.Print("_kInstructionsSnapshot:\n");

  // This head also provides the gap to make the instructions snapshot
  // look like a HeapPage.
  intptr_t instructions_length = next_offset_;
  WriteWordLiteral(instructions_length);
  intptr_t header_words = InstructionsSnapshot::kHeaderSize / sizeof(uword);
  for (intptr_t i = 1; i < header_words; i++) {
    WriteWordLiteral(0);
  }

  Object& owner = Object::Handle(zone);
  String& str = String::Handle(zone);

  for (intptr_t i = 0; i < instructions_.length(); i++) {
    const Instructions& insns = *instructions_[i].insns_;
    const Code& code = *instructions_[i].code_;

    ASSERT(insns.raw()->Size() % sizeof(uint64_t) == 0);

    // 1. Write from the header to the entry point.
    {
      NoSafepointScope no_safepoint;

      uword beginning = reinterpret_cast<uword>(insns.raw_ptr());
      uword entry = beginning + Instructions::HeaderSize();

      ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t)));
      ASSERT(Utils::IsAligned(entry, sizeof(uint64_t)));

      // Write Instructions with the mark and VM heap bits set.
      uword marked_tags = insns.raw_ptr()->tags_;
      marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags);
      marked_tags = RawObject::MarkBit::update(true, marked_tags);

      WriteWordLiteral(marked_tags);
      beginning += sizeof(uword);

      for (uword* cursor = reinterpret_cast<uword*>(beginning);
           cursor < reinterpret_cast<uword*>(entry);
           cursor++) {
        WriteWordLiteral(*cursor);
      }
    }

    // 2. Write a label at the entry point.
    owner = code.owner();
    if (owner.IsNull()) {
      const char* name = StubCode::NameOfStub(insns.EntryPoint());
      assembly_stream_.Print("Precompiled_Stub_%s:\n", name);
    } else if (owner.IsClass()) {
      str = Class::Cast(owner).Name();
      const char* name = str.ToCString();
      EnsureIdentifier(const_cast<char*>(name));
      assembly_stream_.Print("Precompiled_AllocationStub_%s_%" Pd ":\n",
                             name, i);
    } else if (owner.IsFunction()) {
      const char* name = Function::Cast(owner).ToQualifiedCString();
      EnsureIdentifier(const_cast<char*>(name));
      assembly_stream_.Print("Precompiled_%s_%" Pd ":\n", name, i);
    } else {
      UNREACHABLE();
    }

    {
      // 3. Write from the entry point to the end.
      NoSafepointScope no_safepoint;
      uword beginning = reinterpret_cast<uword>(insns.raw()) - kHeapObjectTag;
      uword entry = beginning + Instructions::HeaderSize();
      uword payload_size = insns.size();
      payload_size = Utils::RoundUp(payload_size, OS::PreferredCodeAlignment());
      uword end = entry + payload_size;

      ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t)));
      ASSERT(Utils::IsAligned(entry, sizeof(uint64_t)));
      ASSERT(Utils::IsAligned(end, sizeof(uint64_t)));

      for (uword* cursor = reinterpret_cast<uword*>(entry);
           cursor < reinterpret_cast<uword*>(end);
           cursor++) {
        WriteWordLiteral(*cursor);
      }
    }
  }
#if defined(TARGET_OS_LINUX)
  assembly_stream_.Print(".section .rodata\n");
#elif defined(TARGET_OS_MACOS)
  assembly_stream_.Print(".const\n");
#else
  // Unsupported platform.
  UNREACHABLE();
#endif
  assembly_stream_.Print(".globl _kDataSnapshot\n");
  // Start snapshot at page boundary.
  assembly_stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
  assembly_stream_.Print("_kDataSnapshot:\n");
  WriteWordLiteral(next_object_offset_);  // Data length.
  COMPILE_ASSERT(OS::kMaxPreferredCodeAlignment >= kObjectAlignment);
  assembly_stream_.Print(".balign %" Pd ", 0\n",
                         OS::kMaxPreferredCodeAlignment);

  for (intptr_t i = 0; i < objects_.length(); i++) {
    const Object& obj = *objects_[i].obj_;
    assembly_stream_.Print("Precompiled_Obj_%d:\n", i);

    NoSafepointScope no_safepoint;
    uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag;
    uword end = start + obj.raw()->Size();

    // Write object header with the mark and VM heap bits set.
    uword marked_tags = obj.raw()->ptr()->tags_;
    marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags);
    marked_tags = RawObject::MarkBit::update(true, marked_tags);
    WriteWordLiteral(marked_tags);
    start += sizeof(uword);
    for (uword* cursor = reinterpret_cast<uword*>(start);
         cursor < reinterpret_cast<uword*>(end);
         cursor++) {
      WriteWordLiteral(*cursor);
    }
  }
}


void BlobInstructionsWriter::Write() {
  Zone* zone = Thread::Current()->zone();

  // Handlify collected raw pointers as building the names below
  // will allocate on the Dart heap.
  for (intptr_t i = 0; i < instructions_.length(); i++) {
    InstructionsData& data = instructions_[i];
    data.insns_ = &Instructions::Handle(zone, data.raw_insns_);
    ASSERT(data.raw_code_ != NULL);
    data.code_ = &Code::Handle(zone, data.raw_code_);
  }
  for (intptr_t i = 0; i < objects_.length(); i++) {
    ObjectData& data = objects_[i];
    data.obj_ = &Object::Handle(zone, data.raw_obj_);
  }

  // This head also provides the gap to make the instructions snapshot
  // look like a HeapPage.
  intptr_t instructions_length = next_offset_;
  instructions_blob_stream_.WriteWord(instructions_length);
  intptr_t header_words = InstructionsSnapshot::kHeaderSize / sizeof(uword);
  for (intptr_t i = 1; i < header_words; i++) {
    instructions_blob_stream_.WriteWord(0);
  }

  for (intptr_t i = 0; i < instructions_.length(); i++) {
    const Instructions& insns = *instructions_[i].insns_;

    // 1. Write from the header to the entry point.
    {
      NoSafepointScope no_safepoint;

      uword beginning = reinterpret_cast<uword>(insns.raw_ptr());
      uword entry = beginning + Instructions::HeaderSize();

      ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t)));
      ASSERT(Utils::IsAligned(entry, sizeof(uint64_t)));

      // Write Instructions with the mark and VM heap bits set.
      uword marked_tags = insns.raw_ptr()->tags_;
      marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags);
      marked_tags = RawObject::MarkBit::update(true, marked_tags);

      instructions_blob_stream_.WriteWord(marked_tags);
      beginning += sizeof(uword);

      for (uword* cursor = reinterpret_cast<uword*>(beginning);
           cursor < reinterpret_cast<uword*>(entry);
           cursor++) {
        instructions_blob_stream_.WriteWord(*cursor);
      }
    }

    // 2. Write from the entry point to the end.
    {
      NoSafepointScope no_safepoint;
      uword beginning = reinterpret_cast<uword>(insns.raw()) - kHeapObjectTag;
      uword entry = beginning + Instructions::HeaderSize();
      uword payload_size = insns.size();
      payload_size = Utils::RoundUp(payload_size, OS::PreferredCodeAlignment());
      uword end = entry + payload_size;

      ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t)));
      ASSERT(Utils::IsAligned(entry, sizeof(uint64_t)));
      ASSERT(Utils::IsAligned(end, sizeof(uint64_t)));

      for (uword* cursor = reinterpret_cast<uword*>(entry);
           cursor < reinterpret_cast<uword*>(end);
           cursor++) {
        instructions_blob_stream_.WriteWord(*cursor);
      }
    }
  }

  rodata_blob_stream_.WriteWord(next_object_offset_);  // Data length.
  COMPILE_ASSERT(OS::kMaxPreferredCodeAlignment >= kObjectAlignment);
  while (!Utils::IsAligned(rodata_blob_stream_.bytes_written(),
                           OS::kMaxPreferredCodeAlignment)) {
    rodata_blob_stream_.WriteWord(0);
  }

  for (intptr_t i = 0; i < objects_.length(); i++) {
    const Object& obj = *objects_[i].obj_;

    NoSafepointScope no_safepoint;
    uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag;
    uword end = start + obj.raw()->Size();

    // Write object header with the mark and VM heap bits set.
    uword marked_tags = obj.raw()->ptr()->tags_;
    marked_tags = RawObject::VMHeapObjectTag::update(true, marked_tags);
    marked_tags = RawObject::MarkBit::update(true, marked_tags);
    rodata_blob_stream_.WriteWord(marked_tags);
    start += sizeof(uword);
    for (uword* cursor = reinterpret_cast<uword*>(start);
         cursor < reinterpret_cast<uword*>(end);
         cursor++) {
      rodata_blob_stream_.WriteWord(*cursor);
    }
  }
}


uword InstructionsReader::GetInstructionsAt(int32_t offset) {
  ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment()));
  return reinterpret_cast<uword>(instructions_buffer_) + offset;
}


RawObject* InstructionsReader::GetObjectAt(int32_t offset) {
  ASSERT(Utils::IsAligned(offset, kWordSize));

  RawObject* result =
      reinterpret_cast<RawObject*>(
          reinterpret_cast<uword>(data_buffer_) + offset + kHeapObjectTag);
  ASSERT(result->IsMarked());

  return result;
}


intptr_t SnapshotReader::LookupInternalClass(intptr_t class_header) {
  // If the header is an object Id, lookup singleton VM classes or classes
  // stored in the object store.
  if (IsVMIsolateObject(class_header)) {
    intptr_t class_id = GetVMIsolateObjectId(class_header);
    ASSERT(IsSingletonClassId(class_id));
    return class_id;
  }
  ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
  intptr_t class_id = SerializedHeaderData::decode(class_header);
  ASSERT(IsObjectStoreClassId(class_id) || IsSingletonClassId(class_id));
  return class_id;
}


RawObject* SnapshotReader::AllocateUninitialized(intptr_t class_id,
                                                 intptr_t size) {
  ASSERT_NO_SAFEPOINT_SCOPE();
  ASSERT(Utils::IsAligned(size, kObjectAlignment));

  // Allocate memory where all words look like smis. This is currently
  // only needed for DEBUG-mode validation in StorePointer/StoreSmi, but will
  // be essential with the upcoming deletion barrier.
  uword address =
      old_space()->TryAllocateSmiInitializedLocked(size,
                                                   PageSpace::kForceGrowth);
  if (address == 0) {
    // Use the preallocated out of memory exception to avoid calling
    // into dart code or allocating any code.
    // We do a longjmp at this point to unwind out of the entire
    // read part and return the error object back.
    const UnhandledException& error = UnhandledException::Handle(
        object_store()->preallocated_unhandled_exception());
    thread()->long_jump_base()->Jump(1, error);
  }
  VerifiedMemory::Accept(address, size);

  RawObject* raw_obj = reinterpret_cast<RawObject*>(address + kHeapObjectTag);
  uword tags = 0;
  ASSERT(class_id != kIllegalCid);
  tags = RawObject::ClassIdTag::update(class_id, tags);
  tags = RawObject::SizeTag::update(size, tags);
  tags = RawObject::VMHeapObjectTag::update(is_vm_isolate(), tags);
  raw_obj->ptr()->tags_ = tags;
  return raw_obj;
}


#define READ_VM_SINGLETON_OBJ(id, obj)                                         \
  if (object_id == id) {                                                       \
    return obj;                                                                \
  }                                                                            \

RawObject* SnapshotReader::ReadVMIsolateObject(intptr_t header_value) {
  intptr_t object_id = GetVMIsolateObjectId(header_value);

  // First check if it is one of the singleton objects.
  READ_VM_SINGLETON_OBJ(kNullObject, Object::null());
  READ_VM_SINGLETON_OBJ(kSentinelObject, Object::sentinel().raw());
  READ_VM_SINGLETON_OBJ(kTransitionSentinelObject,
                        Object::transition_sentinel().raw());
  READ_VM_SINGLETON_OBJ(kEmptyArrayObject, Object::empty_array().raw());
  READ_VM_SINGLETON_OBJ(kZeroArrayObject, Object::zero_array().raw());
  READ_VM_SINGLETON_OBJ(kDynamicType, Object::dynamic_type().raw());
  READ_VM_SINGLETON_OBJ(kVoidType, Object::void_type().raw());
  READ_VM_SINGLETON_OBJ(kTrueValue, Bool::True().raw());
  READ_VM_SINGLETON_OBJ(kFalseValue, Bool::False().raw());
  READ_VM_SINGLETON_OBJ(kExtractorParameterTypes,
                        Object::extractor_parameter_types().raw());
  READ_VM_SINGLETON_OBJ(kExtractorParameterNames,
                        Object::extractor_parameter_names().raw());
  READ_VM_SINGLETON_OBJ(kEmptyContextScopeObject,
                        Object::empty_context_scope().raw());
  READ_VM_SINGLETON_OBJ(kEmptyObjectPool, Object::empty_object_pool().raw());
  READ_VM_SINGLETON_OBJ(kEmptyDescriptors, Object::empty_descriptors().raw());
  READ_VM_SINGLETON_OBJ(kEmptyVarDescriptors,
                        Object::empty_var_descriptors().raw());
  READ_VM_SINGLETON_OBJ(kEmptyExceptionHandlers,
                        Object::empty_exception_handlers().raw());

  // Check if it is a double.
  if (object_id == kDoubleObject) {
    ASSERT(kind_ == Snapshot::kMessage);
    return Double::New(ReadDouble());
  }

  // Check it is a singleton class object.
  intptr_t class_id = ClassIdFromObjectId(object_id);
  if (IsSingletonClassId(class_id)) {
    return isolate()->class_table()->At(class_id);  // get singleton class.
  }

  // Check if it is a singleton Argument descriptor object.
  for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
    if (object_id == (kCachedArgumentsDescriptor0 + i)) {
      return ArgumentsDescriptor::cached_args_descriptors_[i];
    }
  }

  // Check if it is a singleton ICData array object.
  for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
    if (object_id == (kCachedICDataArray0 + i)) {
      return ICData::cached_icdata_arrays_[i];
    }
  }

  ASSERT(Symbols::IsVMSymbolId(object_id));
  return Symbols::GetVMSymbol(object_id);  // return VM symbol.
}


RawObject* SnapshotReader::ReadIndexedObject(intptr_t object_id,
                                             intptr_t patch_object_id,
                                             intptr_t patch_offset) {
  intptr_t class_id = ClassIdFromObjectId(object_id);
  if (IsObjectStoreClassId(class_id)) {
    return isolate()->class_table()->At(class_id);  // get singleton class.
  }
  if (!Snapshot::IsFull(kind_)) {
    if (IsObjectStoreTypeId(object_id)) {
      return GetType(object_store(), object_id);  // return type obj.
    }
  }
  ASSERT(object_id >= kMaxPredefinedObjectIds);
  intptr_t index = (object_id - kMaxPredefinedObjectIds);
  if (index < max_vm_isolate_object_id_) {
    return VmIsolateSnapshotObject(index);
  }
  AddPatchRecord(object_id, patch_object_id, patch_offset);
  return GetBackRef(object_id)->raw();
}


void SnapshotReader::AddPatchRecord(intptr_t object_id,
                                    intptr_t patch_object_id,
                                    intptr_t patch_offset) {
  if (patch_object_id != kInvalidPatchIndex && !Snapshot::IsFull(kind())) {
    ASSERT(object_id >= kMaxPredefinedObjectIds);
    intptr_t index = (object_id - kMaxPredefinedObjectIds);
    ASSERT(index >= max_vm_isolate_object_id_);
    index -= max_vm_isolate_object_id_;
    ASSERT(index < backward_references_->length());
    BackRefNode& ref = (*backward_references_)[index];
    ref.AddPatchRecord(patch_object_id, patch_offset);
  }
}


void SnapshotReader::ProcessDeferredCanonicalizations() {
  Type& typeobj = Type::Handle();
  TypeArguments& typeargs = TypeArguments::Handle();
  Object& newobj = Object::Handle();
  for (intptr_t i = 0; i < backward_references_->length(); i++) {
    BackRefNode& backref = (*backward_references_)[i];
    if (backref.defer_canonicalization()) {
      Object* objref = backref.reference();
      // Object should either be a type or a type argument.
      if (objref->IsType()) {
        typeobj ^= objref->raw();
        newobj = typeobj.Canonicalize();
      } else {
        ASSERT(objref->IsTypeArguments());
        typeargs ^= objref->raw();
        newobj = typeargs.Canonicalize();
      }
      if (newobj.raw() != objref->raw()) {
        ZoneGrowableArray<intptr_t>* patches = backref.patch_records();
        ASSERT(newobj.IsCanonical());
        ASSERT(patches != NULL);
        // First we replace the back ref table with the canonical object.
        *objref = newobj.raw();
        // Now we go over all the patch records and patch the canonical object.
        for (intptr_t j = 0; j < patches->length(); j+=2) {
          NoSafepointScope no_safepoint;
          intptr_t patch_object_id = (*patches)[j];
          intptr_t patch_offset = (*patches)[j + 1];
          Object* target = GetBackRef(patch_object_id);
          // We should not backpatch an object that is canonical.
          if (!target->IsCanonical()) {
            RawObject** rawptr =
                reinterpret_cast<RawObject**>(target->raw()->ptr());
            target->StorePointer((rawptr + patch_offset), newobj.raw());
          }
        }
      } else {
        ASSERT(objref->IsCanonical());
      }
    }
  }
}


void SnapshotReader::ArrayReadFrom(intptr_t object_id,
                                   const Array& result,
                                   intptr_t len,
                                   intptr_t tags) {
  // Setup the object fields.
  const intptr_t typeargs_offset =
      GrowableObjectArray::type_arguments_offset() / kWordSize;
  *TypeArgumentsHandle() ^= ReadObjectImpl(kAsInlinedObject,
                                           object_id,
                                           typeargs_offset);
  result.SetTypeArguments(*TypeArgumentsHandle());

  bool as_reference = RawObject::IsCanonical(tags) ? false : true;
  intptr_t offset = result.raw_ptr()->data() -
      reinterpret_cast<RawObject**>(result.raw()->ptr());
  for (intptr_t i = 0; i < len; i++) {
    *PassiveObjectHandle() = ReadObjectImpl(as_reference,
                                            object_id,
                                            (i + offset));
    result.SetAt(i, *PassiveObjectHandle());
  }
}


VmIsolateSnapshotReader::VmIsolateSnapshotReader(
    Snapshot::Kind kind,
    const uint8_t* buffer,
    intptr_t size,
    const uint8_t* instructions_buffer,
    const uint8_t* data_buffer,
    Thread* thread)
      : SnapshotReader(buffer,
                       size,
                       instructions_buffer,
                       data_buffer,
                       kind,
                       new ZoneGrowableArray<BackRefNode>(
                           kNumVmIsolateSnapshotReferences),
                       thread) {
  ASSERT(Snapshot::IsFull(kind));
}


VmIsolateSnapshotReader::~VmIsolateSnapshotReader() {
  intptr_t len = GetBackwardReferenceTable()->length();
  Object::InitVmIsolateSnapshotObjectTable(len);
  ZoneGrowableArray<BackRefNode>* backrefs = GetBackwardReferenceTable();
  for (intptr_t i = 0; i < len; i++) {
    Object::vm_isolate_snapshot_object_table().SetAt(
        i, *(backrefs->At(i).reference()));
  }
  ResetBackwardReferenceTable();
  Dart::set_instructions_snapshot_buffer(instructions_buffer_);
  Dart::set_data_snapshot_buffer(data_buffer_);
}


RawApiError* VmIsolateSnapshotReader::ReadVmIsolateSnapshot() {
  ASSERT(Snapshot::IsFull(kind()));
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  ASSERT(isolate != NULL);
  ASSERT(isolate == Dart::vm_isolate());
  ObjectStore* object_store = isolate->object_store();
  ASSERT(object_store != NULL);

  // First read the version string, and check that it matches.
  RawApiError* error = VerifyVersion();
  if (error != ApiError::null()) {
    return error;
  }

  // The version string matches. Read the rest of the snapshot.

  {
    NoSafepointScope no_safepoint;
    HeapLocker hl(thread, old_space());

    // Read in the symbol table.
    object_store->symbol_table_ = reinterpret_cast<RawArray*>(ReadObject());

    Symbols::InitOnceFromSnapshot(isolate);

    // Read in all the script objects and the accompanying token streams
    // for bootstrap libraries so that they are in the VM isolate's read
    // only memory.
    *(ArrayHandle()) ^= ReadObject();

    if (Snapshot::IncludesCode(kind())) {
      StubCode::ReadFrom(this);
    }

    // Validate the class table.
#if defined(DEBUG)
    isolate->ValidateClassTable();
#endif

    return ApiError::null();
  }
}


IsolateSnapshotReader::IsolateSnapshotReader(Snapshot::Kind kind,
                                             const uint8_t* buffer,
                                             intptr_t size,
                                             const uint8_t* instructions_buffer,
                                             const uint8_t* data_buffer,
                                             Thread* thread)
    : SnapshotReader(buffer,
                     size,
                     instructions_buffer,
                     data_buffer,
                     kind,
                     new ZoneGrowableArray<BackRefNode>(
                         kNumInitialReferencesInFullSnapshot),
                     thread) {
  isolate()->set_compilation_allowed(instructions_buffer_ == NULL);
  ASSERT(Snapshot::IsFull(kind));
}


IsolateSnapshotReader::~IsolateSnapshotReader() {
  ResetBackwardReferenceTable();
}


ScriptSnapshotReader::ScriptSnapshotReader(const uint8_t* buffer,
                                           intptr_t size,
                                           Thread* thread)
    : SnapshotReader(buffer,
                     size,
                     NULL, /* instructions_buffer */
                     NULL, /* data_buffer */
                     Snapshot::kScript,
                     new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
                     thread) {
}


ScriptSnapshotReader::~ScriptSnapshotReader() {
  ResetBackwardReferenceTable();
}


MessageSnapshotReader::MessageSnapshotReader(const uint8_t* buffer,
                                             intptr_t size,
                                             Thread* thread)
    : SnapshotReader(buffer,
                     size,
                     NULL, /* instructions_buffer */
                     NULL, /* data_buffer */
                     Snapshot::kMessage,
                     new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
                     thread) {
}


MessageSnapshotReader::~MessageSnapshotReader() {
  ResetBackwardReferenceTable();
}


SnapshotWriter::SnapshotWriter(Thread* thread,
                               Snapshot::Kind kind,
                               uint8_t** buffer,
                               ReAlloc alloc,
                               intptr_t initial_size,
                               ForwardList* forward_list,
                               InstructionsWriter* instructions_writer,
                               bool can_send_any_object,
                               bool vm_isolate_is_symbolic)
    : BaseWriter(buffer, alloc, initial_size),
      thread_(thread),
      kind_(kind),
      object_store_(isolate()->object_store()),
      class_table_(isolate()->class_table()),
      forward_list_(forward_list),
      instructions_writer_(instructions_writer),
      exception_type_(Exceptions::kNone),
      exception_msg_(NULL),
      unmarked_objects_(false),
      can_send_any_object_(can_send_any_object),
      vm_isolate_is_symbolic_(vm_isolate_is_symbolic) {
  ASSERT(forward_list_ != NULL);
}


void SnapshotWriter::WriteObject(RawObject* rawobj) {
  WriteObjectImpl(rawobj, kAsInlinedObject);
  WriteForwardedObjects();
}


uword SnapshotWriter::GetObjectTags(RawObject* raw) {
  return raw->ptr()->tags_;
}


#define VM_OBJECT_CLASS_LIST(V)                                                \
  V(OneByteString)                                                             \
  V(TwoByteString)                                                             \
  V(Mint)                                                                      \
  V(Bigint)                                                                    \
  V(Double)                                                                    \
  V(ImmutableArray)                                                            \

#define VM_OBJECT_WRITE(clazz)                                                 \
  case clazz::kClassId: {                                                      \
    object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized);       \
    Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(rawobj);               \
        raw_obj->WriteTo(this, object_id, kind(), false);                      \
    return true;                                                               \
  }                                                                            \

#define WRITE_VM_SINGLETON_OBJ(obj, id)                                        \
  if (rawobj == obj) {                                                         \
    WriteVMIsolateObject(id);                                                  \
    return true;                                                               \
  }                                                                            \

bool SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
  // Check if it is one of the singleton VM objects.
  WRITE_VM_SINGLETON_OBJ(Object::null(), kNullObject);
  WRITE_VM_SINGLETON_OBJ(Object::sentinel().raw(), kSentinelObject);
  WRITE_VM_SINGLETON_OBJ(Object::transition_sentinel().raw(),
                         kTransitionSentinelObject);
  WRITE_VM_SINGLETON_OBJ(Object::empty_array().raw(), kEmptyArrayObject);
  WRITE_VM_SINGLETON_OBJ(Object::zero_array().raw(), kZeroArrayObject);
  WRITE_VM_SINGLETON_OBJ(Object::dynamic_type().raw(), kDynamicType);
  WRITE_VM_SINGLETON_OBJ(Object::void_type().raw(), kVoidType);
  WRITE_VM_SINGLETON_OBJ(Bool::True().raw(), kTrueValue);
  WRITE_VM_SINGLETON_OBJ(Bool::False().raw(), kFalseValue);
  WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_types().raw(),
                         kExtractorParameterTypes);
  WRITE_VM_SINGLETON_OBJ(Object::extractor_parameter_names().raw(),
                         kExtractorParameterNames);
  WRITE_VM_SINGLETON_OBJ(Object::empty_context_scope().raw(),
                         kEmptyContextScopeObject);
  WRITE_VM_SINGLETON_OBJ(Object::empty_object_pool().raw(), kEmptyObjectPool);
  WRITE_VM_SINGLETON_OBJ(Object::empty_descriptors().raw(), kEmptyDescriptors);
  WRITE_VM_SINGLETON_OBJ(Object::empty_var_descriptors().raw(),
                         kEmptyVarDescriptors);
  WRITE_VM_SINGLETON_OBJ(Object::empty_exception_handlers().raw(),
                         kEmptyExceptionHandlers);

  // Check if it is a singleton class object which is shared by
  // all isolates.
  intptr_t id = rawobj->GetClassId();
  if (id == kClassCid) {
    RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj);
    intptr_t class_id = raw_class->ptr()->id_;
    if (IsSingletonClassId(class_id)) {
      intptr_t object_id = ObjectIdFromClassId(class_id);
      WriteVMIsolateObject(object_id);
      return true;
    }
  }

  // Check if it is a singleton Argument descriptor object.
  for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
    if (rawobj == ArgumentsDescriptor::cached_args_descriptors_[i]) {
      WriteVMIsolateObject(kCachedArgumentsDescriptor0 + i);
      return true;
    }
  }

  // Check if it is a singleton ICData array object.
  for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
    if (rawobj == ICData::cached_icdata_arrays_[i]) {
      WriteVMIsolateObject(kCachedICDataArray0 + i);
      return true;
    }
  }

  if (Snapshot::IsFull(kind())) {
    // Check it is a predefined symbol in the VM isolate.
    id = Symbols::LookupVMSymbol(rawobj);
    if (id != kInvalidIndex) {
      WriteVMIsolateObject(id);
      return true;
    }

    // Check if it is an object from the vm isolate snapshot object table.
    id = FindVmSnapshotObject(rawobj);
    if (id != kInvalidIndex) {
      WriteIndexedObject(id);
      return true;
    }
  } else {
    // In the case of script snapshots or for messages we do not use
    // the index into the vm isolate snapshot object table, instead we
    // explicitly write the object out.
    intptr_t object_id = forward_list_->FindObject(rawobj);
    if (object_id != -1) {
      WriteIndexedObject(object_id);
      return true;
    } else {
      switch (id) {
        VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE)
        case kTypedDataUint32ArrayCid: {
          object_id = forward_list_->AddObject(zone(), rawobj, kIsSerialized);
          RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(rawobj);
          raw_obj->WriteTo(this, object_id, kind(), false);
          return true;
        }
        default:
          OS::Print("class id = %" Pd "\n", id);
          break;
      }
    }
  }

  if (!vm_isolate_is_symbolic()) {
    return false;
  }

  const Object& obj = Object::Handle(rawobj);
  FATAL1("Unexpected reference to object in VM isolate: %s\n", obj.ToCString());
  return false;
}

#undef VM_OBJECT_WRITE


// An object visitor which will iterate over all the script objects in the heap
// and either count them or collect them into an array. This is used during
// full snapshot generation of the VM isolate to write out all script
// objects and their accompanying token streams.
class ScriptVisitor : public ObjectVisitor {
 public:
  explicit ScriptVisitor(Thread* thread) :
      objHandle_(Object::Handle(thread->zone())),
      count_(0),
      scripts_(NULL) {}

  ScriptVisitor(Thread* thread, const Array* scripts) :
      objHandle_(Object::Handle(thread->zone())),
      count_(0),
      scripts_(scripts) {}

  void VisitObject(RawObject* obj) {
    if (obj->IsScript()) {
      if (scripts_ != NULL) {
        objHandle_ = obj;
        scripts_->SetAt(count_, objHandle_);
      }
      count_ += 1;
    }
  }

  intptr_t count() const { return count_; }

 private:
  Object& objHandle_;
  intptr_t count_;
  const Array* scripts_;
};


FullSnapshotWriter::FullSnapshotWriter(Snapshot::Kind kind,
                                       uint8_t** vm_isolate_snapshot_buffer,
                                       uint8_t** isolate_snapshot_buffer,
                                       ReAlloc alloc,
                                       InstructionsWriter* instructions_writer,
                                       bool vm_isolate_is_symbolic)
    : thread_(Thread::Current()),
      kind_(kind),
      vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer),
      isolate_snapshot_buffer_(isolate_snapshot_buffer),
      alloc_(alloc),
      vm_isolate_snapshot_size_(0),
      isolate_snapshot_size_(0),
      forward_list_(NULL),
      instructions_writer_(instructions_writer),
      scripts_(Array::Handle(zone())),
      symbol_table_(Array::Handle(zone())),
      vm_isolate_is_symbolic_(vm_isolate_is_symbolic) {
  ASSERT(isolate_snapshot_buffer_ != NULL);
  ASSERT(alloc_ != NULL);
  ASSERT(isolate() != NULL);
  ASSERT(ClassFinalizer::AllClassesFinalized());
  ASSERT(isolate() != NULL);
  ASSERT(heap() != NULL);
  ObjectStore* object_store = isolate()->object_store();
  ASSERT(object_store != NULL);
  // Ensure the class table is valid.
#if defined(DEBUG)
  isolate()->ValidateClassTable();
#endif

  // Collect all the script objects and their accompanying token stream objects
  // into an array so that we can write it out as part of the VM isolate
  // snapshot. We first count the number of script objects, allocate an array
  // and then fill it up with the script objects.
  ScriptVisitor scripts_counter(thread());
  heap()->IterateOldObjects(&scripts_counter);
  intptr_t count = scripts_counter.count();
  scripts_ = Array::New(count, Heap::kOld);
  ScriptVisitor script_visitor(thread(), &scripts_);
  heap()->IterateOldObjects(&script_visitor);

  if (vm_isolate_snapshot_buffer != NULL) {
    // Stash the symbol table away for writing and reading into the vm isolate,
    // and reset the symbol table for the regular isolate so that we do not
    // write these symbols into the snapshot of a regular dart isolate.
    symbol_table_ = object_store->symbol_table();
    Symbols::SetupSymbolTable(isolate());
  }

  forward_list_ = new ForwardList(thread(), SnapshotWriter::FirstObjectId());
  ASSERT(forward_list_ != NULL);
}


FullSnapshotWriter::~FullSnapshotWriter() {
  delete forward_list_;
  // We may run Dart code afterwards, restore the symbol table if needed.
  if (!symbol_table_.IsNull()) {
    isolate()->object_store()->set_symbol_table(symbol_table_);
    symbol_table_ = Array::null();
  }
  scripts_ = Array::null();
}


void FullSnapshotWriter::WriteVmIsolateSnapshot() {
  ASSERT(vm_isolate_snapshot_buffer_ != NULL);
  SnapshotWriter writer(thread(),
                        kind_,
                        vm_isolate_snapshot_buffer_,
                        alloc_,
                        kInitialSize,
                        forward_list_,
                        instructions_writer_,
                        true, /* can_send_any_object */
                        vm_isolate_is_symbolic_);
  // Write full snapshot for the VM isolate.
  // Setup for long jump in case there is an exception while writing
  // the snapshot.
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    // Reserve space in the output buffer for a snapshot header.
    writer.ReserveHeader();

    // Write out the version string.
    writer.WriteVersion();

    /*
     * Now Write out the following
     * - the symbol table
     * - all the scripts and token streams for these scripts
     *
     **/
    // Write out the symbol table.
    writer.WriteObject(symbol_table_.raw());

    // Write out all the script objects and the accompanying token streams
    // for the bootstrap libraries so that they are in the VM isolate
    // read only memory.
    writer.WriteObject(scripts_.raw());

    if (Snapshot::IncludesCode(kind_)) {
      ASSERT(!vm_isolate_is_symbolic_);
      StubCode::WriteTo(&writer);
    }


    writer.FillHeader(writer.kind());

    vm_isolate_snapshot_size_ = writer.BytesWritten();
  } else {
    writer.ThrowException(writer.exception_type(), writer.exception_msg());
  }
}


void FullSnapshotWriter::WriteIsolateFullSnapshot() {
  SnapshotWriter writer(thread(),
                        kind_,
                        isolate_snapshot_buffer_,
                        alloc_,
                        kInitialSize,
                        forward_list_,
                        instructions_writer_,
                        true, /* can_send_any_object */
                        true /* vm_isolate_is_symbolic */);
  ObjectStore* object_store = isolate()->object_store();
  ASSERT(object_store != NULL);

  // Write full snapshot for a regular isolate.
  // Setup for long jump in case there is an exception while writing
  // the snapshot.
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    // Reserve space in the output buffer for a snapshot header.
    writer.ReserveHeader();

    // Write out the version string.
    writer.WriteVersion();

    // Write out the full snapshot.

    // Write out all the objects in the object store of the isolate which
    // is the root set for all dart allocated objects at this point.
    SnapshotWriterVisitor visitor(&writer, false);
    visitor.VisitPointers(object_store->from(),
                          object_store->to_snapshot(kind_));

    // Write out all forwarded objects.
    writer.WriteForwardedObjects();

    writer.FillHeader(writer.kind());

    isolate_snapshot_size_ = writer.BytesWritten();
  } else {
    writer.ThrowException(writer.exception_type(), writer.exception_msg());
  }
}


void FullSnapshotWriter::WriteFullSnapshot() {
  if (vm_isolate_snapshot_buffer() != NULL) {
    WriteVmIsolateSnapshot();
  }
  WriteIsolateFullSnapshot();
  if (Snapshot::IncludesCode(kind_)) {
    instructions_writer_->Write();

    OS::Print("VMIsolate(CodeSize): %" Pd "\n", VmIsolateSnapshotSize());
    OS::Print("Isolate(CodeSize): %" Pd "\n", IsolateSnapshotSize());
    OS::Print("Instructions(CodeSize): %" Pd "\n",
              instructions_writer_->binary_size());
    intptr_t total = VmIsolateSnapshotSize() +
                     IsolateSnapshotSize() +
                     instructions_writer_->binary_size();
    OS::Print("Total(CodeSize): %" Pd "\n", total);
  }
}


PrecompiledSnapshotWriter::PrecompiledSnapshotWriter(
    uint8_t** vm_isolate_snapshot_buffer,
    uint8_t** isolate_snapshot_buffer,
    ReAlloc alloc,
    InstructionsWriter* instructions_writer)
  : FullSnapshotWriter(Snapshot::kAppNoJIT,
                       vm_isolate_snapshot_buffer,
                       isolate_snapshot_buffer,
                       alloc,
                       instructions_writer,
                       false /* vm_isolate_is_symbolic */) {
}


PrecompiledSnapshotWriter::~PrecompiledSnapshotWriter() {}


ForwardList::ForwardList(Thread* thread, intptr_t first_object_id)
    : thread_(thread),
      first_object_id_(first_object_id),
      nodes_(),
      first_unprocessed_object_id_(first_object_id) {
}


ForwardList::~ForwardList() {
  heap()->ResetObjectIdTable();
}


intptr_t ForwardList::AddObject(Zone* zone,
                                RawObject* raw,
                                SerializeState state) {
  NoSafepointScope no_safepoint;
  intptr_t object_id = next_object_id();
  ASSERT(object_id > 0 && object_id <= kMaxObjectId);
  const Object& obj = Object::ZoneHandle(zone, raw);
  Node* node = new Node(&obj, state);
  ASSERT(node != NULL);
  nodes_.Add(node);
  ASSERT(SnapshotWriter::FirstObjectId() > 0);
  ASSERT(object_id != 0);
  heap()->SetObjectId(raw, object_id);
  return object_id;
}


intptr_t ForwardList::FindObject(RawObject* raw) {
  NoSafepointScope no_safepoint;
  ASSERT(SnapshotWriter::FirstObjectId() > 0);
  intptr_t id = heap()->GetObjectId(raw);
  ASSERT(id == 0 || NodeForObjectId(id)->obj()->raw() == raw);
  return (id == 0) ? static_cast<intptr_t>(kInvalidIndex) : id;
}


bool SnapshotWriter::CheckAndWritePredefinedObject(RawObject* rawobj) {
  // Check if object can be written in one of the following ways:
  // - Smi: the Smi value is written as is (last bit is not tagged).
  // - VM internal class (from VM isolate): (index of class in vm isolate | 0x3)
  // - Object that has already been written: (negative id in stream | 0x3)

  NoSafepointScope no_safepoint;

  // First check if it is a Smi (i.e not a heap object).
  if (!rawobj->IsHeapObject()) {
    Write<int64_t>(reinterpret_cast<intptr_t>(rawobj));
    return true;
  }

  intptr_t cid = rawobj->GetClassId();

  if ((kind_ == Snapshot::kMessage) && (cid == kDoubleCid)) {
    WriteVMIsolateObject(kDoubleObject);
    RawDouble* rd = reinterpret_cast<RawDouble*>(rawobj);
    WriteDouble(rd->ptr()->value_);
    return true;
  }

  // Check if object has already been serialized, in that case just write
  // the object id out.
  intptr_t object_id = forward_list_->FindObject(rawobj);
  if (object_id != kInvalidIndex) {
    WriteIndexedObject(object_id);
    return true;
  }

  // Now check if it is an object from the VM isolate. These objects are shared
  // by all isolates.
  if (rawobj->IsVMHeapObject() && HandleVMIsolateObject(rawobj)) {
    return true;
  }

  // Check if it is a code object in that case just write a Null object
  // as we do not want code objects in the snapshot.
  if (cid == kCodeCid && !Snapshot::IncludesCode(kind_)) {
    WriteVMIsolateObject(kNullObject);
    return true;
  }

  // Check if classes are not being serialized and it is preinitialized type
  // or a predefined internal VM class in the object store.
  if (!Snapshot::IsFull(kind_)) {
    // Check if it is an internal VM class which is in the object store.
    if (cid == kClassCid) {
      RawClass* raw_class = reinterpret_cast<RawClass*>(rawobj);
      intptr_t class_id = raw_class->ptr()->id_;
      if (IsObjectStoreClassId(class_id)) {
        intptr_t object_id = ObjectIdFromClassId(class_id);
        WriteIndexedObject(object_id);
        return true;
      }
    }

    // Now check it is a preinitialized type object.
    RawType* raw_type = reinterpret_cast<RawType*>(rawobj);
    intptr_t index = GetTypeIndex(object_store(), raw_type);
    if (index != kInvalidIndex) {
      WriteIndexedObject(index);
      return true;
    }
  }

  return false;
}


void SnapshotWriter::WriteObjectImpl(RawObject* raw, bool as_reference) {
  // First check if object can be written as a simple predefined type.
  if (CheckAndWritePredefinedObject(raw)) {
    return;
  }

  // When we know that we are dealing with leaf or shallow objects we write
  // these objects inline even when 'as_reference' is true.
  const bool write_as_reference = as_reference && !raw->IsCanonical();
  intptr_t tags = raw->ptr()->tags_;

  // Add object to the forward ref list and mark it so that future references
  // to this object in the snapshot will use this object id. Mark the
  // serialization state so that we do the right thing when we go through
  // the forward list.
  intptr_t class_id = raw->GetClassId();
  intptr_t object_id;
  if (write_as_reference && IsSplitClassId(class_id)) {
    object_id = forward_list_->AddObject(zone(), raw, kIsNotSerialized);
  } else {
    object_id = forward_list_->AddObject(zone(), raw, kIsSerialized);
  }
  if (write_as_reference || !IsSplitClassId(class_id)) {
    object_id = kOmittedObjectId;
  }
  WriteMarkedObjectImpl(raw, tags, object_id, write_as_reference);
}


void SnapshotWriter::WriteMarkedObjectImpl(RawObject* raw,
                                           intptr_t tags,
                                           intptr_t object_id,
                                           bool as_reference) {
  NoSafepointScope no_safepoint;
  RawClass* cls = class_table_->At(RawObject::ClassIdTag::decode(tags));
  intptr_t class_id = cls->ptr()->id_;
  ASSERT(class_id == RawObject::ClassIdTag::decode(tags));
  if (class_id >= kNumPredefinedCids ||
      RawObject::IsImplicitFieldClassId(class_id)) {
    WriteInstance(raw, cls, tags, object_id, as_reference);
    return;
  }
  switch (class_id) {
#define SNAPSHOT_WRITE(clazz)                                                  \
    case clazz::kClassId: {                                                    \
      Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(raw);                \
          raw_obj->WriteTo(this, object_id, kind_, as_reference);              \
      return;                                                                  \
    }                                                                          \

    CLASS_LIST_NO_OBJECT(SNAPSHOT_WRITE)
#undef SNAPSHOT_WRITE
#define SNAPSHOT_WRITE(clazz)                                                  \
    case kTypedData##clazz##Cid:                                               \

    CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
      RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(raw);
      raw_obj->WriteTo(this, object_id, kind_, as_reference);
      return;
    }
#undef SNAPSHOT_WRITE
#define SNAPSHOT_WRITE(clazz)                                                  \
    case kExternalTypedData##clazz##Cid:                                       \

    CLASS_LIST_TYPED_DATA(SNAPSHOT_WRITE) {
      RawExternalTypedData* raw_obj =
        reinterpret_cast<RawExternalTypedData*>(raw);
      raw_obj->WriteTo(this, object_id, kind_, as_reference);
      return;
    }
#undef SNAPSHOT_WRITE
    default: break;
  }

  const Object& obj = Object::Handle(raw);
  FATAL1("Unexpected object: %s\n", obj.ToCString());
}


class WriteInlinedObjectVisitor : public ObjectVisitor {
 public:
  explicit WriteInlinedObjectVisitor(SnapshotWriter* writer)
      : writer_(writer) {}

  virtual void VisitObject(RawObject* obj) {
    intptr_t object_id = writer_->forward_list_->FindObject(obj);
    ASSERT(object_id != kInvalidIndex);
    intptr_t tags = writer_->GetObjectTags(obj);
    writer_->WriteMarkedObjectImpl(obj, tags, object_id, kAsInlinedObject);
  }

 private:
  SnapshotWriter* writer_;
};


void SnapshotWriter::WriteForwardedObjects() {
  WriteInlinedObjectVisitor visitor(this);
  forward_list_->SerializeAll(&visitor);
}


void ForwardList::SerializeAll(ObjectVisitor* writer) {
  // Write out all objects that were added to the forward list and have
  // not been serialized yet. These would typically be fields of instance
  // objects, arrays or immutable arrays (this is done in order to avoid
  // deep recursive calls to WriteObjectImpl).
  // NOTE: The forward list might grow as we process the list.
#ifdef DEBUG
  for (intptr_t i = first_object_id(); i < first_unprocessed_object_id_; ++i) {
    ASSERT(NodeForObjectId(i)->is_serialized());
  }
#endif  // DEBUG
  for (intptr_t id = first_unprocessed_object_id_;
       id < next_object_id();
       ++id) {
    if (!NodeForObjectId(id)->is_serialized()) {
      // Write the object out in the stream.
      RawObject* raw = NodeForObjectId(id)->obj()->raw();
      writer->VisitObject(raw);

      // Mark object as serialized.
      NodeForObjectId(id)->set_state(kIsSerialized);
    }
  }
  first_unprocessed_object_id_ = next_object_id();
}


void SnapshotWriter::WriteClassId(RawClass* cls) {
  ASSERT(!Snapshot::IsFull(kind_));
  int class_id = cls->ptr()->id_;
  ASSERT(!IsSingletonClassId(class_id) && !IsObjectStoreClassId(class_id));

  // Write out the library url and class name.
  RawLibrary* library = cls->ptr()->library_;
  ASSERT(library != Library::null());
  WriteObjectImpl(library->ptr()->url_, kAsInlinedObject);
  WriteObjectImpl(cls->ptr()->name_, kAsInlinedObject);
}


void SnapshotWriter::WriteFunctionId(RawFunction* func, bool owner_is_class) {
  ASSERT(kind_ == Snapshot::kScript);
  RawClass* cls = (owner_is_class) ?
      reinterpret_cast<RawClass*>(func->ptr()->owner_) :
      reinterpret_cast<RawPatchClass*>(
          func->ptr()->owner_)->ptr()->patched_class_;

  // Write out the library url and class name.
  RawLibrary* library = cls->ptr()->library_;
  ASSERT(library != Library::null());
  WriteObjectImpl(library->ptr()->url_, kAsInlinedObject);
  WriteObjectImpl(cls->ptr()->name_, kAsInlinedObject);
  WriteObjectImpl(func->ptr()->name_, kAsInlinedObject);
}


void SnapshotWriter::WriteStaticImplicitClosure(intptr_t object_id,
                                                RawFunction* func,
                                                intptr_t tags) {
  // Write out the serialization header value for this object.
  WriteInlinedObjectHeader(object_id);

  // Indicate this is a static implicit closure object.
  Write<int32_t>(SerializedHeaderData::encode(kStaticImplicitClosureObjectId));

  // Write out the tags.
  WriteTags(tags);

  // Write out the library url, class name and signature function name.
  RawClass* cls = GetFunctionOwner(func);
  ASSERT(cls != Class::null());
  RawLibrary* library = cls->ptr()->library_;
  ASSERT(library != Library::null());
  WriteObjectImpl(library->ptr()->url_, kAsInlinedObject);
  WriteObjectImpl(cls->ptr()->name_, kAsInlinedObject);
  WriteObjectImpl(func->ptr()->name_, kAsInlinedObject);
}


void SnapshotWriter::ArrayWriteTo(intptr_t object_id,
                                  intptr_t array_kind,
                                  intptr_t tags,
                                  RawSmi* length,
                                  RawTypeArguments* type_arguments,
                                  RawObject* data[],
                                  bool as_reference) {
  if (as_reference) {
    // Write out the serialization header value for this object.
    WriteInlinedObjectHeader(kOmittedObjectId);

    // Write out the class information.
    WriteIndexedObject(array_kind);
    WriteTags(tags);

    // Write out the length field.
    Write<RawObject*>(length);
  } else {
    intptr_t len = Smi::Value(length);

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

    // Write out the class and tags information.
    WriteIndexedObject(array_kind);
    WriteTags(tags);

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

    // Write out the type arguments.
    WriteObjectImpl(type_arguments, kAsInlinedObject);

    // Write out the individual object ids.
    bool write_as_reference = RawObject::IsCanonical(tags) ? false : true;
    for (intptr_t i = 0; i < len; i++) {
      WriteObjectImpl(data[i], write_as_reference);
    }
  }
}


RawFunction* SnapshotWriter::IsSerializableClosure(RawClosure* closure) {
  // Extract the function object to check if this closure
  // can be sent in an isolate message.
  RawFunction* func = closure->ptr()->function_;
  // We only allow closure of top level methods or static functions in a
  // class to be sent in isolate messages.
  if (can_send_any_object() &&
      Function::IsImplicitStaticClosureFunction(func)) {
    return func;
  }
  // Not a closure of a top level method or static function, throw an
  // exception as we do not allow these objects to be serialized.
  HANDLESCOPE(thread());

  const Function& errorFunc = Function::Handle(zone(), func);
  ASSERT(!errorFunc.IsNull());

  // All other closures are errors.
  char* chars = OS::SCreate(thread()->zone(),
      "Illegal argument in isolate message : (object is a closure - %s)",
      errorFunc.ToCString());
  SetWriteException(Exceptions::kArgument, chars);
  return Function::null();
}


RawClass* SnapshotWriter::GetFunctionOwner(RawFunction* func) {
  RawObject* owner = func->ptr()->owner_;
  uword tags = GetObjectTags(owner);
  intptr_t class_id = RawObject::ClassIdTag::decode(tags);
  if (class_id == kClassCid) {
    return reinterpret_cast<RawClass*>(owner);
  }
  ASSERT(class_id == kPatchClassCid);
  return reinterpret_cast<RawPatchClass*>(owner)->ptr()->patched_class_;
}


void SnapshotWriter::CheckForNativeFields(RawClass* cls) {
  if (cls->ptr()->num_native_fields_ != 0) {
    // We do not allow objects with native fields in an isolate message.
    HANDLESCOPE(thread());
    const Class& clazz = Class::Handle(zone(), cls);
    char* chars = OS::SCreate(thread()->zone(),
        "Illegal argument in isolate message"
        " : (object extends NativeWrapper - %s)",
        clazz.ToCString());
    SetWriteException(Exceptions::kArgument, chars);
  }
}


void SnapshotWriter::SetWriteException(Exceptions::ExceptionType type,
                                       const char* msg) {
  set_exception_type(type);
  set_exception_msg(msg);
  // The more specific error is set up in SnapshotWriter::ThrowException().
  thread()->long_jump_base()->
      Jump(1, Object::snapshot_writer_error());
}


void SnapshotWriter::WriteInstance(RawObject* raw,
                                   RawClass* cls,
                                   intptr_t tags,
                                   intptr_t object_id,
                                   bool as_reference) {
  // Closure instances are handled by RawClosure::WriteTo().
  ASSERT(!Class::IsClosureClass(cls));

  // Check if the instance has native fields and throw an exception if it does.
  CheckForNativeFields(cls);

  // Object is regular dart instance.
  if (as_reference) {
    // Write out the serialization header value for this object.
    WriteInlinedObjectHeader(kOmittedObjectId);

    // Indicate this is an instance object.
    Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId));
    WriteTags(tags);

    // Write out the class information for this object.
    WriteObjectImpl(cls, kAsInlinedObject);
  } else {
    intptr_t next_field_offset =
        cls->ptr()->next_field_offset_in_words_ << kWordSizeLog2;
    ASSERT(next_field_offset > 0);

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

    // Indicate this is an instance object.
    Write<int32_t>(SerializedHeaderData::encode(kInstanceObjectId));

    // Write out the tags.
    WriteTags(tags);

    // Write out the class information for this object.
    WriteObjectImpl(cls, kAsInlinedObject);

    // Write out all the fields for the object.
    // Instance::NextFieldOffset() returns the offset of the first field in
    // a Dart object.
    bool write_as_reference = RawObject::IsCanonical(tags) ? false : true;
    intptr_t offset = Instance::NextFieldOffset();
    while (offset < next_field_offset) {
      RawObject* raw_obj = *reinterpret_cast<RawObject**>(
          reinterpret_cast<uword>(raw->ptr()) + offset);
      WriteObjectImpl(raw_obj, write_as_reference);
      offset += kWordSize;
    }
  }
  return;
}


bool SnapshotWriter::AllowObjectsInDartLibrary(RawLibrary* library) {
  return (library == object_store()->collection_library() ||
          library == object_store()->core_library() ||
          library == object_store()->typed_data_library());
}


intptr_t SnapshotWriter::FindVmSnapshotObject(RawObject* rawobj) {
  intptr_t length = Object::vm_isolate_snapshot_object_table().Length();
  for (intptr_t i = 0; i < length; i++) {
    if (Object::vm_isolate_snapshot_object_table().At(i) == rawobj) {
      return (i + kMaxPredefinedObjectIds);
    }
  }
  return kInvalidIndex;
}


void SnapshotWriter::ThrowException(Exceptions::ExceptionType type,
                                    const char* msg) {
  thread()->clear_sticky_error();
  if (msg != NULL) {
    const String& msg_obj = String::Handle(String::New(msg));
    const Array& args = Array::Handle(Array::New(1));
    args.SetAt(0, msg_obj);
    Exceptions::ThrowByType(type, args);
  } else {
    Exceptions::ThrowByType(type, Object::empty_array());
  }
  UNREACHABLE();
}


void SnapshotWriter::WriteVersion() {
  const char* expected_version = Version::SnapshotString();
  ASSERT(expected_version != NULL);
  const intptr_t version_len = strlen(expected_version);
  WriteBytes(reinterpret_cast<const uint8_t*>(expected_version), version_len);
}


intptr_t SnapshotWriter::FirstObjectId() {
  intptr_t max_vm_isolate_object_id =
      Object::vm_isolate_snapshot_object_table().Length();
  return kMaxPredefinedObjectIds + max_vm_isolate_object_id;
}


ScriptSnapshotWriter::ScriptSnapshotWriter(uint8_t** buffer,
                                           ReAlloc alloc)
    : SnapshotWriter(Thread::Current(),
                     Snapshot::kScript,
                     buffer,
                     alloc,
                     kInitialSize,
                     &forward_list_,
                     NULL, /* instructions_writer */
                     true, /* can_send_any_object */
                     true /* vm_isolate_is_symbolic */),
      forward_list_(thread(), kMaxPredefinedObjectIds) {
  ASSERT(buffer != NULL);
  ASSERT(alloc != NULL);
}


void ScriptSnapshotWriter::WriteScriptSnapshot(const Library& lib) {
  ASSERT(kind() == Snapshot::kScript);
  ASSERT(isolate() != NULL);
  ASSERT(ClassFinalizer::AllClassesFinalized());

  // Setup for long jump in case there is an exception while writing
  // the snapshot.
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    // Reserve space in the output buffer for a snapshot header.
    ReserveHeader();

    // Write out the version string.
    WriteVersion();

    // Write out the library object.
    {
      NoSafepointScope no_safepoint;

      // Write out the library object.
      WriteObject(lib.raw());

      FillHeader(kind());
    }
  } else {
    ThrowException(exception_type(), exception_msg());
  }
}


void SnapshotWriterVisitor::VisitPointers(RawObject** first, RawObject** last) {
  for (RawObject** current = first; current <= last; current++) {
    RawObject* raw_obj = *current;
    writer_->WriteObjectImpl(raw_obj, as_references_);
  }
}


MessageWriter::MessageWriter(uint8_t** buffer,
                             ReAlloc alloc,
                             bool can_send_any_object)
    : SnapshotWriter(Thread::Current(),
                     Snapshot::kMessage,
                     buffer,
                     alloc,
                     kInitialSize,
                     &forward_list_,
                     NULL, /* instructions_writer */
                     can_send_any_object,
                     true /* vm_isolate_is_symbolic */),
      forward_list_(thread(), kMaxPredefinedObjectIds) {
  ASSERT(buffer != NULL);
  ASSERT(alloc != NULL);
}


void MessageWriter::WriteMessage(const Object& obj) {
  ASSERT(kind() == Snapshot::kMessage);
  ASSERT(isolate() != NULL);

  // Setup for long jump in case there is an exception while writing
  // the message.
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    NoSafepointScope no_safepoint;
    WriteObject(obj.raw());
  } else {
    ThrowException(exception_type(), exception_msg());
  }
}


}  // namespace dart
