summaryrefslogtreecommitdiff
path: root/runtime/quick_exception_handler.cc
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2014-07-16 11:56:07 +0200
committerSebastien Hertz <shertz@google.com>2014-07-17 20:43:37 +0200
commitc901dd7bdc80b953d04100ef2f54b8d1ca5f466b (patch)
treede52f83ac4dab4ca5b48cbc5a4701abdc762f2d1 /runtime/quick_exception_handler.cc
parent81457a3cd8fca14396b5785a4e4c8070c259b07a (diff)
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
Diffstat (limited to 'runtime/quick_exception_handler.cc')
-rw-r--r--runtime/quick_exception_handler.cc38
1 files changed, 36 insertions, 2 deletions
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<int32_t>& kinds) {
+ return static_cast<VRegKind>(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<int32_t> kinds = verifier.DescribeVRegs(dex_pc);
+ const std::vector<int32_t> kinds(verifier.DescribeVRegs(dex_pc));
for (uint16_t reg = 0; reg < num_regs; ++reg) {
- VRegKind kind = static_cast<VRegKind>(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<mirror::Object*>(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;