| 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) {
|
|
|