Index: runtime/vm/object.cc |
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
index 9787d2bd8b68055bd450b97bb6ebfc8106734a99..e2fbcff1c9bac6fb2db2ba6d084802d133c0176e 100644 |
--- a/runtime/vm/object.cc |
+++ b/runtime/vm/object.cc |
@@ -6780,7 +6780,7 @@ const char* ExceptionHandlers::ToCString() const { |
} |
-intptr_t DeoptInfo::Length() const { |
+intptr_t DeoptInfo::GetLength() const { |
return Smi::Value(raw_ptr()->length_); |
} |
@@ -6795,25 +6795,66 @@ intptr_t DeoptInfo::Instruction(intptr_t index) const { |
} |
+intptr_t DeoptInfo::TranslationLength() const { |
+ intptr_t length = GetLength(); |
+ if (Instruction(length - 1) != DeoptInstr::kSuffix) return length; |
+ |
+ // If the last command is a suffix, add in the length of the suffix and |
+ // do not count the suffix command as a translation command. |
+ intptr_t ignored = 0; |
+ intptr_t suffix_length = |
+ DeoptInstr::DecodeSuffix(FromIndex(length - 1), &ignored); |
+ return length + suffix_length - 1; |
+} |
+ |
+ |
+void DeoptInfo::ToInstructions(const Array& table, |
+ GrowableArray<DeoptInstr*>* instructions) const { |
+ ASSERT(instructions->is_empty()); |
+ Smi& offset = Smi::Handle(); |
+ DeoptInfo& info = DeoptInfo::Handle(raw()); |
+ Smi& reason = Smi::Handle(); |
+ intptr_t index = 0; |
+ intptr_t length = TranslationLength(); |
+ while (index < length) { |
+ intptr_t instruction = info.Instruction(index); |
+ intptr_t from_index = info.FromIndex(index); |
+ if (instruction == DeoptInstr::kSuffix) { |
+ // Suffix instructions cause us to 'jump' to another translation, |
+ // changing info, length and index. |
+ intptr_t info_number = 0; |
+ intptr_t suffix_length = |
+ DeoptInstr::DecodeSuffix(from_index, &info_number); |
+ DeoptTable::GetEntry(table, info_number, &offset, &info, &reason); |
+ length = info.TranslationLength(); |
+ index = length - suffix_length; |
+ } else { |
+ instructions->Add(DeoptInstr::Create(instruction, from_index)); |
+ ++index; |
+ } |
+ } |
+} |
+ |
+ |
const char* DeoptInfo::ToCString() const { |
- if (Length() == 0) { |
+ if (GetLength() == 0) { |
return "No DeoptInfo"; |
} |
// Convert to DeoptInstr. |
- GrowableArray<DeoptInstr*> deopt_instrs(Length()); |
- for (intptr_t i = 0; i < Length(); i++) { |
+ GrowableArray<DeoptInstr*> deopt_instrs(GetLength()); |
+ for (intptr_t i = 0; i < GetLength(); i++) { |
deopt_instrs.Add(DeoptInstr::Create(Instruction(i), FromIndex(i))); |
} |
// Compute the buffer size required. |
intptr_t len = 1; // Trailing '\0'. |
- for (intptr_t i = 0; i < Length(); i++) { |
+ for (intptr_t i = 0; i < GetLength(); i++) { |
len += OS::SNPrint(NULL, 0, "[%s]", deopt_instrs[i]->ToCString()); |
} |
// Allocate the buffer. |
char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len); |
// Layout the fields in the buffer. |
intptr_t index = 0; |
- for (intptr_t i = 0; i < Length(); i++) { |
+ for (intptr_t i = 0; i < GetLength(); i++) { |
index += OS::SNPrint((buffer + index), |
(len - index), |
"[%s]", |