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
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 6581f9b..41d6989 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -194,6 +194,10 @@
   }
 
  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 @@
                                       &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 @@
           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;