| Index: runtime/vm/snapshot.cc
 | 
| diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
 | 
| index 936acbd5364ae84662b610be2f9eda945e8f28fd..472979820c3a6a476c9da091ea1c137a7939b19c 100644
 | 
| --- a/runtime/vm/snapshot.cc
 | 
| +++ b/runtime/vm/snapshot.cc
 | 
| @@ -1196,7 +1196,7 @@ static void EnsureIdentifier(char* label) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void InstructionsWriter::WriteAssembly() {
 | 
| +void AssemblyInstructionsWriter::Write() {
 | 
|    Zone* zone = Thread::Current()->zone();
 | 
|  
 | 
|    // Handlify collected raw pointers as building the names below
 | 
| @@ -1212,12 +1212,12 @@ void InstructionsWriter::WriteAssembly() {
 | 
|      data.obj_ = &Object::Handle(zone, data.raw_obj_);
 | 
|    }
 | 
|  
 | 
| -  stream_.Print(".text\n");
 | 
| -  stream_.Print(".globl _kInstructionsSnapshot\n");
 | 
| +  assembly_stream_.Print(".text\n");
 | 
| +  assembly_stream_.Print(".globl _kInstructionsSnapshot\n");
 | 
|    // Start snapshot at page boundary.
 | 
|    ASSERT(VirtualMemory::PageSize() >= OS::kMaxPreferredCodeAlignment);
 | 
| -  stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
 | 
| -  stream_.Print("_kInstructionsSnapshot:\n");
 | 
| +  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.
 | 
| @@ -1241,16 +1241,17 @@ void InstructionsWriter::WriteAssembly() {
 | 
|      owner = code.owner();
 | 
|      if (owner.IsNull()) {
 | 
|        const char* name = StubCode::NameOfStub(insns.EntryPoint());
 | 
| -      stream_.Print("Precompiled_Stub_%s:\n", name);
 | 
| +      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));
 | 
| -      stream_.Print("Precompiled_AllocationStub_%s_%" Pd ":\n", name, i);
 | 
| +      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));
 | 
| -      stream_.Print("Precompiled_%s_%" Pd ":\n", name, i);
 | 
| +      assembly_stream_.Print("Precompiled_%s_%" Pd ":\n", name, i);
 | 
|      } else {
 | 
|        UNREACHABLE();
 | 
|      }
 | 
| @@ -1276,24 +1277,25 @@ void InstructionsWriter::WriteAssembly() {
 | 
|      }
 | 
|    }
 | 
|  #if defined(TARGET_OS_LINUX)
 | 
| -  stream_.Print(".section .rodata\n");
 | 
| +  assembly_stream_.Print(".section .rodata\n");
 | 
|  #elif defined(TARGET_OS_MACOS)
 | 
| -  stream_.Print(".const\n");
 | 
| +  assembly_stream_.Print(".const\n");
 | 
|  #else
 | 
|    // Unsupported platform.
 | 
|    UNREACHABLE();
 | 
|  #endif
 | 
| -  stream_.Print(".globl _kDataSnapshot\n");
 | 
| +  assembly_stream_.Print(".globl _kDataSnapshot\n");
 | 
|    // Start snapshot at page boundary.
 | 
| -  stream_.Print(".balign %" Pd ", 0\n", VirtualMemory::PageSize());
 | 
| -  stream_.Print("_kDataSnapshot:\n");
 | 
| +  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);
 | 
| -  stream_.Print(".balign %" Pd ", 0\n", OS::kMaxPreferredCodeAlignment);
 | 
| +  assembly_stream_.Print(".balign %" Pd ", 0\n",
 | 
| +                         OS::kMaxPreferredCodeAlignment);
 | 
|  
 | 
|    for (intptr_t i = 0; i < objects_.length(); i++) {
 | 
|      const Object& obj = *objects_[i].obj_;
 | 
| -    stream_.Print("Precompiled_Obj_%d:\n", i);
 | 
| +    assembly_stream_.Print("Precompiled_Obj_%d:\n", i);
 | 
|  
 | 
|      NoSafepointScope no_safepoint;
 | 
|      uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag;
 | 
| @@ -1314,6 +1316,84 @@ void InstructionsWriter::WriteAssembly() {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +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_;
 | 
| +
 | 
| +    {
 | 
| +      // 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;
 | 
| @@ -1883,20 +1963,18 @@ class ScriptVisitor : public ObjectVisitor {
 | 
|  
 | 
|  FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
 | 
|                                         uint8_t** isolate_snapshot_buffer,
 | 
| -                                       uint8_t** instructions_snapshot_buffer,
 | 
|                                         ReAlloc alloc,
 | 
| +                                       InstructionsWriter* instructions_writer,
 | 
|                                         bool snapshot_code,
 | 
|                                         bool vm_isolate_is_symbolic)
 | 
|      : thread_(Thread::Current()),
 | 
|        vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer),
 | 
|        isolate_snapshot_buffer_(isolate_snapshot_buffer),
 | 
| -      instructions_snapshot_buffer_(instructions_snapshot_buffer),
 | 
|        alloc_(alloc),
 | 
|        vm_isolate_snapshot_size_(0),
 | 
|        isolate_snapshot_size_(0),
 | 
| -      instructions_snapshot_size_(0),
 | 
|        forward_list_(NULL),
 | 
| -      instructions_writer_(NULL),
 | 
| +      instructions_writer_(instructions_writer),
 | 
|        scripts_(Array::Handle(zone())),
 | 
|        symbol_table_(Array::Handle(zone())),
 | 
|        snapshot_code_(snapshot_code),
 | 
| @@ -1935,12 +2013,6 @@ FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
 | 
|  
 | 
|    forward_list_ = new ForwardList(thread(), SnapshotWriter::FirstObjectId());
 | 
|    ASSERT(forward_list_ != NULL);
 | 
| -
 | 
| -  if (instructions_snapshot_buffer != NULL) {
 | 
| -    instructions_writer_ = new InstructionsWriter(instructions_snapshot_buffer,
 | 
| -                                                  alloc,
 | 
| -                                                  kInitialSize);
 | 
| -  }
 | 
|  }
 | 
|  
 | 
|  
 | 
| @@ -2059,8 +2131,7 @@ void FullSnapshotWriter::WriteFullSnapshot() {
 | 
|    }
 | 
|    WriteIsolateFullSnapshot();
 | 
|    if (snapshot_code_) {
 | 
| -    instructions_writer_->WriteAssembly();
 | 
| -    instructions_snapshot_size_ = instructions_writer_->BytesWritten();
 | 
| +    instructions_writer_->Write();
 | 
|  
 | 
|      OS::Print("VMIsolate(CodeSize): %" Pd "\n", VmIsolateSnapshotSize());
 | 
|      OS::Print("Isolate(CodeSize): %" Pd "\n", IsolateSnapshotSize());
 | 
| @@ -2077,12 +2148,12 @@ void FullSnapshotWriter::WriteFullSnapshot() {
 | 
|  PrecompiledSnapshotWriter::PrecompiledSnapshotWriter(
 | 
|      uint8_t** vm_isolate_snapshot_buffer,
 | 
|      uint8_t** isolate_snapshot_buffer,
 | 
| -    uint8_t** instructions_snapshot_buffer,
 | 
| -    ReAlloc alloc)
 | 
| +    ReAlloc alloc,
 | 
| +    InstructionsWriter* instructions_writer)
 | 
|    : FullSnapshotWriter(vm_isolate_snapshot_buffer,
 | 
|                         isolate_snapshot_buffer,
 | 
| -                       instructions_snapshot_buffer,
 | 
|                         alloc,
 | 
| +                       instructions_writer,
 | 
|                         true, /* snapshot_code */
 | 
|                         false /* vm_isolate_is_symbolic */) {
 | 
|  }
 | 
| 
 |