From c901dd7bdc80b953d04100ef2f54b8d1ca5f466b Mon Sep 17 00:00:00 2001 From: Sebastien Hertz Date: Wed, 16 Jul 2014 11:56:07 +0200 Subject: Fix access to long/double stack values from debugger Long and double values live in a pair of DEX registers. When we compile DEX code with the Quick compiler, a DEX register either lives in the stack or is promoted to a physical register. In the case of a pair of DEX registers, the Quick compiler assumes both registers live in the same "area": both live in the stack or both are promoted to physical registers. From the debugger, we used to access these values by reading/writing each DEX register separately. However, this does not work when only one DEX register of a pair is promoted and the other lives in the stack. In this case, the compiled code reads from/writes to the stack only. To fix that, the debugger must follow the same rule than the Quick compiler: if both DEX registers are promoted, read/write them from/to physical registers, otherwise read/write them from/to the stack. We add StackVisitor:GetVRegPair and StackVisitor:SetVRegPair for this purpose. We also follow the same rule when deoptimizing. However we need to do that only when we know two consecutive DEX registers are part of a pair (long or double). We know that thanks to the verifier. Bug: 15527793 Change-Id: I04812285ff26ef0129f39792a1cf776f3591ca2d --- runtime/quick_exception_handler.cc | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'runtime/quick_exception_handler.cc') diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index 6581f9b627..41d69894d5 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -194,6 +194,10 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor { } private: + static VRegKind GetVRegKind(uint16_t reg, const std::vector& kinds) { + return static_cast(kinds.at(reg * 2)); + } + bool HandleDeoptimization(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { const DexFile::CodeItem* code_item = m->GetCodeItem(); CHECK(code_item != nullptr); @@ -210,9 +214,9 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor { &m->GetClassDef(), code_item, m->GetDexMethodIndex(), m, m->GetAccessFlags(), false, true, true); verifier.Verify(); - std::vector kinds = verifier.DescribeVRegs(dex_pc); + const std::vector kinds(verifier.DescribeVRegs(dex_pc)); for (uint16_t reg = 0; reg < num_regs; ++reg) { - VRegKind kind = static_cast(kinds.at(reg * 2)); + VRegKind kind = GetVRegKind(reg, kinds); switch (kind) { case kUndefined: new_frame->SetVReg(reg, 0xEBADDE09); @@ -224,6 +228,36 @@ class DeoptimizeStackVisitor FINAL : public StackVisitor { new_frame->SetVRegReference(reg, reinterpret_cast(GetVReg(m, reg, kind))); break; + case kLongLoVReg: + if (GetVRegKind(reg + 1, kinds), kLongHiVReg) { + // Treat it as a "long" register pair. + new_frame->SetVRegLong(reg, GetVRegPair(m, reg, kLongLoVReg, kLongHiVReg)); + } else { + new_frame->SetVReg(reg, GetVReg(m, reg, kind)); + } + break; + case kLongHiVReg: + if (GetVRegKind(reg - 1, kinds), kLongLoVReg) { + // Nothing to do: we treated it as a "long" register pair. + } else { + new_frame->SetVReg(reg, GetVReg(m, reg, kind)); + } + break; + case kDoubleLoVReg: + if (GetVRegKind(reg + 1, kinds), kDoubleHiVReg) { + // Treat it as a "double" register pair. + new_frame->SetVRegLong(reg, GetVRegPair(m, reg, kDoubleLoVReg, kDoubleHiVReg)); + } else { + new_frame->SetVReg(reg, GetVReg(m, reg, kind)); + } + break; + case kDoubleHiVReg: + if (GetVRegKind(reg - 1, kinds), kDoubleLoVReg) { + // Nothing to do: we treated it as a "double" register pair. + } else { + new_frame->SetVReg(reg, GetVReg(m, reg, kind)); + } + break; default: new_frame->SetVReg(reg, GetVReg(m, reg, kind)); break; -- cgit v1.2.3-59-g8ed1b