Index: runtime/vm/deopt_instructions.cc |
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc |
index 3e26df5895ab85c7698d4396b5334bdf31c86264..fa90ec270e3a57f4b3f0095a4b8e73b4b759ac60 100644 |
--- a/runtime/vm/deopt_instructions.cc |
+++ b/runtime/vm/deopt_instructions.cc |
@@ -1379,4 +1379,109 @@ void DeoptTable::GetEntry(const Array& table, |
*reason ^= table.At(i + 2); |
} |
+ |
+intptr_t DeoptInfo::FrameSize(const TypedData& packed) { |
+ NoSafepointScope no_safepoint; |
+ typedef ReadStream::Raw<sizeof(intptr_t), intptr_t> Reader; |
+ ReadStream read_stream(reinterpret_cast<uint8_t*>(packed.DataAddr(0)), |
+ packed.LengthInBytes()); |
+ return Reader::Read(&read_stream); |
+} |
+ |
+ |
+intptr_t DeoptInfo::NumMaterializations( |
+ const GrowableArray<DeoptInstr*>& unpacked) { |
+ intptr_t num = 0; |
+ while (unpacked[num]->kind() == DeoptInstr::kMaterializeObject) { |
+ num++; |
+ } |
+ return num; |
+} |
+ |
+ |
+void DeoptInfo::UnpackInto(const Array& table, |
+ const TypedData& packed, |
+ GrowableArray<DeoptInstr*>* unpacked, |
+ intptr_t length) { |
+ NoSafepointScope no_safepoint; |
+ typedef ReadStream::Raw<sizeof(intptr_t), intptr_t> Reader; |
+ ReadStream read_stream(reinterpret_cast<uint8_t*>(packed.DataAddr(0)), |
+ packed.LengthInBytes()); |
+ const intptr_t frame_size = Reader::Read(&read_stream); // Skip frame size. |
+ USE(frame_size); |
+ |
+ const intptr_t suffix_length = Reader::Read(&read_stream); |
+ if (suffix_length != 0) { |
+ ASSERT(suffix_length > 1); |
+ const intptr_t info_number = Reader::Read(&read_stream); |
+ |
+ TypedData& suffix = TypedData::Handle(); |
+ Smi& offset = Smi::Handle(); |
+ Smi& reason_and_flags = Smi::Handle(); |
+ DeoptTable::GetEntry(table, info_number, &offset, &suffix, |
+ &reason_and_flags); |
+ UnpackInto(table, suffix, unpacked, suffix_length); |
+ } |
+ |
+ while ((read_stream.PendingBytes() > 0) && (unpacked->length() < length)) { |
+ const intptr_t instruction = Reader::Read(&read_stream); |
+ const intptr_t from_index = Reader::Read(&read_stream); |
+ unpacked->Add(DeoptInstr::Create(instruction, from_index)); |
+ } |
+} |
+ |
+ |
+void DeoptInfo::Unpack(const Array& table, |
+ const TypedData& packed, |
+ GrowableArray<DeoptInstr*>* unpacked) { |
+ ASSERT(unpacked->is_empty()); |
+ |
+ // Pass kMaxInt32 as the length to unpack all instructions from the |
+ // packed stream. |
+ UnpackInto(table, packed, unpacked, kMaxInt32); |
+ |
+ unpacked->Reverse(); |
+} |
+ |
+ |
+const char* DeoptInfo::ToCString(const Array& deopt_table, |
+ const TypedData& packed) { |
+#define FORMAT "[%s]" |
+ GrowableArray<DeoptInstr*> deopt_instrs; |
+ Unpack(deopt_table, packed, &deopt_instrs); |
+ |
+ // Compute the buffer size required. |
+ intptr_t len = 1; // Trailing '\0'. |
+ for (intptr_t i = 0; i < deopt_instrs.length(); i++) { |
+ len += OS::SNPrint(NULL, 0, FORMAT, deopt_instrs[i]->ToCString()); |
+ } |
+ |
+ // Allocate the buffer. |
+ char* buffer = Thread::Current()->zone()->Alloc<char>(len); |
+ |
+ // Layout the fields in the buffer. |
+ intptr_t index = 0; |
+ for (intptr_t i = 0; i < deopt_instrs.length(); i++) { |
+ index += OS::SNPrint((buffer + index), (len - index), FORMAT, |
+ deopt_instrs[i]->ToCString()); |
+ } |
+ |
+ return buffer; |
+#undef FORMAT |
+} |
+ |
+ |
+// Returns a bool so it can be asserted. |
+bool DeoptInfo::VerifyDecompression(const GrowableArray<DeoptInstr*>& original, |
+ const Array& deopt_table, |
+ const TypedData& packed) { |
+ GrowableArray<DeoptInstr*> unpacked; |
+ Unpack(deopt_table, packed, &unpacked); |
+ ASSERT(unpacked.length() == original.length()); |
+ for (intptr_t i = 0; i < unpacked.length(); ++i) { |
+ ASSERT(unpacked[i]->Equals(*original[i])); |
+ } |
+ return true; |
+} |
+ |
} // namespace dart |