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