Index: runtime/vm/snapshot.cc |
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc |
index 8a755bdb3f51b9dad33b62b2d2e0b22f9aab2db4..b336512c34e069296cf0a687f84b6510a9bf6772 100644 |
--- a/runtime/vm/snapshot.cc |
+++ b/runtime/vm/snapshot.cc |
@@ -1138,18 +1138,106 @@ RawStacktrace* SnapshotReader::NewStacktrace() { |
int32_t InstructionsWriter::GetOffsetFor(RawInstructions* instructions) { |
- // Instructions are allocated with the code alignment and we don't write |
- // anything else in the text section. |
- ASSERT(Utils::IsAligned(stream_.bytes_written(), |
- OS::PreferredCodeAlignment())); |
- |
- intptr_t offset = stream_.bytes_written(); |
- stream_.WriteBytes(reinterpret_cast<uint8_t*>(instructions) - kHeapObjectTag, |
- instructions->Size()); |
+ intptr_t offset = next_offset_; |
+ next_offset_ += instructions->Size(); |
+ instructions_.Add(InstructionsData(instructions)); |
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 InstructionsWriter::WriteAssembly() { |
+ Zone* Z = 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(Z, data.raw_insns_); |
+ ASSERT(data.raw_code_ != NULL); |
+ data.code_ = &Code::Handle(Z, data.raw_code_); |
+ } |
+ |
+ stream_.Print(".text\n"); |
+ stream_.Print(".globl _kInstructionsSnapshot\n"); |
+ stream_.Print(".balign %" Pd ", 0\n", OS::PreferredCodeAlignment()); |
+ stream_.Print("_kInstructionsSnapshot:\n"); |
+ |
+ Object& owner = Object::Handle(Z); |
+ String& str = String::Handle(Z); |
+ |
+ 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()) - kHeapObjectTag; |
+ uword entry = beginning + Instructions::HeaderSize(); |
+ |
+ ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t))); |
+ ASSERT(Utils::IsAligned(entry, sizeof(uint64_t))); |
+ |
+ for (uint64_t* cursor = reinterpret_cast<uint64_t*>(beginning); |
+ cursor < reinterpret_cast<uint64_t*>(entry); |
+ cursor++) { |
+ stream_.Print(".quad 0x%0.16" Px64 "\n", *cursor); |
+ } |
+ } |
+ |
+ // 2. Write a label at the entry point. |
+ owner = code.owner(); |
+ if (owner.IsNull()) { |
+ const char* name = StubCode::NameOfStub(insns.EntryPoint()); |
+ 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); |
+ } else if (owner.IsFunction()) { |
+ const char* name = Function::Cast(owner).ToQualifiedCString(); |
+ EnsureIdentifier(const_cast<char*>(name)); |
+ 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 end = beginning + insns.raw()->Size(); |
+ |
+ ASSERT(Utils::IsAligned(beginning, sizeof(uint64_t))); |
+ ASSERT(Utils::IsAligned(entry, sizeof(uint64_t))); |
+ ASSERT(Utils::IsAligned(end, sizeof(uint64_t))); |
+ |
+ for (uint64_t* cursor = reinterpret_cast<uint64_t*>(entry); |
+ cursor < reinterpret_cast<uint64_t*>(end); |
+ cursor++) { |
+ stream_.Print(".quad 0x%0.16" Px64 "\n", *cursor); |
+ } |
+ } |
+ } |
+} |
+ |
+ |
RawInstructions* InstructionsReader::GetInstructionsAt(int32_t offset, |
uword expected_tags) { |
ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment())); |
@@ -1944,6 +2032,7 @@ void FullSnapshotWriter::WriteFullSnapshot() { |
} |
WriteIsolateFullSnapshot(); |
+ instructions_writer_->WriteAssembly(); |
instructions_snapshot_size_ = instructions_writer_->BytesWritten(); |
} else { |
if (vm_isolate_snapshot_buffer() != NULL) { |