| Index: runtime/vm/object.cc
|
| diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
|
| index 0fda4e48c5fdea78e20feddb11eb607bde8ba93b..50ce7d7d9f89d97e3cc748807361d00e3a738efd 100644
|
| --- a/runtime/vm/object.cc
|
| +++ b/runtime/vm/object.cc
|
| @@ -142,7 +142,6 @@ RawClass* Object::var_descriptors_class_ =
|
| reinterpret_cast<RawClass*>(RAW_NULL);
|
| RawClass* Object::exception_handlers_class_ =
|
| reinterpret_cast<RawClass*>(RAW_NULL);
|
| -RawClass* Object::deopt_info_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
| RawClass* Object::context_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
| RawClass* Object::context_scope_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
| RawClass* Object::icdata_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
|
| @@ -559,9 +558,6 @@ void Object::InitOnce(Isolate* isolate) {
|
| cls = Class::New<ExceptionHandlers>();
|
| exception_handlers_class_ = cls.raw();
|
|
|
| - cls = Class::New<DeoptInfo>();
|
| - deopt_info_class_ = cls.raw();
|
| -
|
| cls = Class::New<Context>();
|
| context_class_ = cls.raw();
|
|
|
| @@ -816,7 +812,6 @@ void Object::FinalizeVMIsolate(Isolate* isolate) {
|
| SET_CLASS_NAME(stackmap, Stackmap);
|
| SET_CLASS_NAME(var_descriptors, LocalVarDescriptors);
|
| SET_CLASS_NAME(exception_handlers, ExceptionHandlers);
|
| - SET_CLASS_NAME(deopt_info, DeoptInfo);
|
| SET_CLASS_NAME(context, Context);
|
| SET_CLASS_NAME(context_scope, ContextScope);
|
| SET_CLASS_NAME(icdata, ICData);
|
| @@ -3209,8 +3204,6 @@ RawString* Class::GenerateUserVisibleName() const {
|
| return Symbols::LocalVarDescriptors().raw();
|
| case kExceptionHandlersCid:
|
| return Symbols::ExceptionHandlers().raw();
|
| - case kDeoptInfoCid:
|
| - return Symbols::DeoptInfo().raw();
|
| case kContextCid:
|
| return Symbols::Context().raw();
|
| case kContextScopeCid:
|
| @@ -11140,113 +11133,104 @@ void ExceptionHandlers::PrintJSONImpl(JSONStream* stream,
|
| }
|
|
|
|
|
| -intptr_t DeoptInfo::Length() const {
|
| - return Smi::Value(raw_ptr()->length_);
|
| -}
|
| -
|
| -
|
| -intptr_t DeoptInfo::FromIndex(intptr_t index) const {
|
| +intptr_t DeoptInfo::FrameSize(const TypedData& packed) {
|
| NoSafepointScope no_safepoint;
|
| - return *(EntryAddr(index, kFromIndex));
|
| + 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::Instruction(intptr_t index) const {
|
| - NoSafepointScope no_safepoint;
|
| - return *(EntryAddr(index, kInstruction));
|
| +intptr_t DeoptInfo::NumMaterializations(
|
| + const GrowableArray<DeoptInstr*>& unpacked) {
|
| + intptr_t num = 0;
|
| + while (unpacked[num]->kind() == DeoptInstr::kMaterializeObject) {
|
| + num++;
|
| + }
|
| + return num;
|
| }
|
|
|
|
|
| -intptr_t DeoptInfo::FrameSize() const {
|
| - return TranslationLength() - NumMaterializations();
|
| -}
|
| +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);
|
|
|
| -intptr_t DeoptInfo::TranslationLength() const {
|
| - intptr_t length = Length();
|
| - if (Instruction(length - 1) != DeoptInstr::kSuffix) return length;
|
| + 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);
|
| + }
|
|
|
| - // 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;
|
| + 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));
|
| + }
|
| }
|
|
|
|
|
| -intptr_t DeoptInfo::NumMaterializations() const {
|
| - intptr_t pos = 0;
|
| - while (Instruction(pos) == DeoptInstr::kMaterializeObject) {
|
| - pos++;
|
| - }
|
| - return pos;
|
| -}
|
| +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);
|
|
|
| -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_and_flags = 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_and_flags);
|
| - length = info.TranslationLength();
|
| - index = length - suffix_length;
|
| - } else {
|
| - instructions->Add(DeoptInstr::Create(instruction, from_index));
|
| - ++index;
|
| - }
|
| - }
|
| + unpacked->Reverse();
|
| }
|
|
|
|
|
| -const char* DeoptInfo::ToCString() const {
|
| - if (Length() == 0) {
|
| - return "No DeoptInfo";
|
| - }
|
| - // Convert to DeoptInstr.
|
| - GrowableArray<DeoptInstr*> deopt_instrs(Length());
|
| - for (intptr_t i = 0; i < Length(); i++) {
|
| - deopt_instrs.Add(DeoptInstr::Create(Instruction(i), FromIndex(i)));
|
| - }
|
| +const char* DeoptInfo::ToCString(const Array& deopt_table,
|
| + const TypedData& packed) {
|
| + 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 < Length(); i++) {
|
| + for (intptr_t i = 0; i < deopt_instrs.length(); 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 < deopt_instrs.length(); i++) {
|
| index += OS::SNPrint((buffer + index),
|
| (len - index),
|
| "[%s]",
|
| deopt_instrs[i]->ToCString());
|
| }
|
| +
|
| return buffer;
|
| }
|
|
|
|
|
| // Returns a bool so it can be asserted.
|
| bool DeoptInfo::VerifyDecompression(const GrowableArray<DeoptInstr*>& original,
|
| - const Array& deopt_table) const {
|
| - intptr_t length = TranslationLength();
|
| - GrowableArray<DeoptInstr*> unpacked(length);
|
| - ToInstructions(deopt_table, &unpacked);
|
| + 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]));
|
| @@ -11255,47 +11239,6 @@ bool DeoptInfo::VerifyDecompression(const GrowableArray<DeoptInstr*>& original,
|
| }
|
|
|
|
|
| -void DeoptInfo::PrintJSONImpl(JSONStream* stream, bool ref) const {
|
| - Object::PrintJSONImpl(stream, ref);
|
| -}
|
| -
|
| -
|
| -RawDeoptInfo* DeoptInfo::New(intptr_t num_commands) {
|
| - ASSERT(Object::deopt_info_class() != Class::null());
|
| - if ((num_commands < 0) || (num_commands > kMaxElements)) {
|
| - FATAL1("Fatal error in DeoptInfo::New(): invalid num_commands %" Pd "\n",
|
| - num_commands);
|
| - }
|
| - DeoptInfo& result = DeoptInfo::Handle();
|
| - {
|
| - uword size = DeoptInfo::InstanceSize(num_commands);
|
| - RawObject* raw = Object::Allocate(DeoptInfo::kClassId,
|
| - size,
|
| - Heap::kOld);
|
| - NoSafepointScope no_safepoint;
|
| - result ^= raw;
|
| - result.SetLength(num_commands);
|
| - }
|
| - return result.raw();
|
| -}
|
| -
|
| -
|
| -void DeoptInfo::SetLength(intptr_t value) const {
|
| - // This is only safe because we create a new Smi, which does not cause
|
| - // heap allocation.
|
| - StoreSmi(&raw_ptr()->length_, Smi::New(value));
|
| -}
|
| -
|
| -
|
| -void DeoptInfo::SetAt(intptr_t index,
|
| - intptr_t instr_kind,
|
| - intptr_t from_index) const {
|
| - NoSafepointScope no_safepoint;
|
| - *(EntryAddr(index, kInstruction)) = instr_kind;
|
| - *(EntryAddr(index, kFromIndex)) = from_index;
|
| -}
|
| -
|
| -
|
| const char* ICData::ToCString() const {
|
| const char* kFormat = "ICData target:'%s' num-args: %" Pd
|
| " num-checks: %" Pd "";
|
| @@ -12108,7 +12051,7 @@ bool Code::HasBreakpoint() const {
|
| }
|
|
|
|
|
| -RawDeoptInfo* Code::GetDeoptInfoAtPc(uword pc,
|
| +RawTypedData* Code::GetDeoptInfoAtPc(uword pc,
|
| ICData::DeoptReasonId* deopt_reason,
|
| uint32_t* deopt_flags) const {
|
| ASSERT(is_optimized());
|
| @@ -12120,7 +12063,7 @@ RawDeoptInfo* Code::GetDeoptInfoAtPc(uword pc,
|
| intptr_t length = DeoptTable::GetLength(table);
|
| Smi& offset = Smi::Handle();
|
| Smi& reason_and_flags = Smi::Handle();
|
| - DeoptInfo& info = DeoptInfo::Handle();
|
| + TypedData& info = TypedData::Handle();
|
| for (intptr_t i = 0; i < length; ++i) {
|
| DeoptTable::GetEntry(table, i, &offset, &info, &reason_and_flags);
|
| if (pc == (code_entry + offset.Value())) {
|
| @@ -12131,7 +12074,7 @@ RawDeoptInfo* Code::GetDeoptInfoAtPc(uword pc,
|
| }
|
| }
|
| *deopt_reason = ICData::kDeoptUnknown;
|
| - return DeoptInfo::null();
|
| + return TypedData::null();
|
| }
|
|
|
|
|
|
|