Disable dex register descriptions.

Disable dex register descriptions. Make GetVReg and SetVReg frame
routines fail in unimplementeds.

Change-Id: I0f05a188d3c81c424018b52e2dcea40891cd307e
diff --git a/src/monitor.cc b/src/monitor.cc
index a7d08bc..149babf 100644
--- a/src/monitor.cc
+++ b/src/monitor.cc
@@ -915,34 +915,40 @@
     return; // No "tries" implies no synchronization, so no held locks to report.
   }
 
-  // Ask the verifier for the dex pcs of all the monitor-enter instructions corresponding to
-  // the locks held in this stack frame.
-  std::vector<uint32_t> monitor_enter_dex_pcs;
-  verifier::MethodVerifier::FindLocksAtDexPc(m, stack_visitor->GetDexPc(), monitor_enter_dex_pcs);
-  if (monitor_enter_dex_pcs.empty()) {
-    return;
-  }
-
-  // Verification is an iterative process, so it can visit the same monitor-enter instruction
-  // repeatedly with increasingly accurate type information. Our callers don't want to see
-  // duplicates.
-  STLSortAndRemoveDuplicates(&monitor_enter_dex_pcs);
-
-  for (size_t i = 0; i < monitor_enter_dex_pcs.size(); ++i) {
-    // The verifier works in terms of the dex pcs of the monitor-enter instructions.
-    // We want the registers used by those instructions (so we can read the values out of them).
-    uint32_t dex_pc = monitor_enter_dex_pcs[i];
-    uint16_t monitor_enter_instruction = code_item->insns_[dex_pc];
-
-    // Quick sanity check.
-    if ((monitor_enter_instruction & 0xff) != Instruction::MONITOR_ENTER) {
-      LOG(FATAL) << "expected monitor-enter @" << dex_pc << "; was "
-                 << reinterpret_cast<void*>(monitor_enter_instruction);
+  // TODO: Enable dex register lock descriptions, disabling as for the portable path GetVReg is
+  // unimplemented. There is also a possible deadlock relating to the verifier calling
+  // ClassLoader.loadClass and reentering managed code whilst the ThreadList lock is held.
+  const bool kEnableDexRegisterLockDescriptions = false;
+  if (kEnableDexRegisterLockDescriptions) {
+    // Ask the verifier for the dex pcs of all the monitor-enter instructions corresponding to
+    // the locks held in this stack frame.
+    std::vector<uint32_t> monitor_enter_dex_pcs;
+    verifier::MethodVerifier::FindLocksAtDexPc(m, stack_visitor->GetDexPc(), monitor_enter_dex_pcs);
+    if (monitor_enter_dex_pcs.empty()) {
+      return;
     }
 
-    uint16_t monitor_register = ((monitor_enter_instruction >> 8) & 0xff);
-    Object* o = reinterpret_cast<Object*>(stack_visitor->GetVReg(m, monitor_register));
-    DumpLockedObject(os, o);
+    // Verification is an iterative process, so it can visit the same monitor-enter instruction
+    // repeatedly with increasingly accurate type information. Our callers don't want to see
+    // duplicates.
+    STLSortAndRemoveDuplicates(&monitor_enter_dex_pcs);
+
+    for (size_t i = 0; i < monitor_enter_dex_pcs.size(); ++i) {
+      // The verifier works in terms of the dex pcs of the monitor-enter instructions.
+      // We want the registers used by those instructions (so we can read the values out of them).
+      uint32_t dex_pc = monitor_enter_dex_pcs[i];
+      uint16_t monitor_enter_instruction = code_item->insns_[dex_pc];
+
+      // Quick sanity check.
+      if ((monitor_enter_instruction & 0xff) != Instruction::MONITOR_ENTER) {
+        LOG(FATAL) << "expected monitor-enter @" << dex_pc << "; was "
+            << reinterpret_cast<void*>(monitor_enter_instruction);
+      }
+
+      uint16_t monitor_register = ((monitor_enter_instruction >> 8) & 0xff);
+      Object* o = reinterpret_cast<Object*>(stack_visitor->GetVReg(m, monitor_register));
+      DumpLockedObject(os, o);
+    }
   }
 }
 
diff --git a/src/stack.cc b/src/stack.cc
index 67b9bfa..dd319bc 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -106,55 +106,65 @@
 }
 
 uint32_t StackVisitor::GetVReg(Method* m, int vreg) const {
-  DCHECK(context_ != NULL); // You can't reliably read registers without a context.
-  DCHECK(m == GetMethod());
-  uint32_t core_spills = m->GetCoreSpillMask();
-  const VmapTable vmap_table(m->GetVmapTableRaw());
-  uint32_t vmap_offset;
-  // TODO: IsInContext stops before spotting floating point registers.
-  if (vmap_table.IsInContext(vreg, vmap_offset)) {
-    // Compute the register we need to load from the context.
-    uint32_t spill_mask = core_spills;
-    CHECK_LT(vmap_offset, static_cast<uint32_t>(__builtin_popcount(spill_mask)));
-    uint32_t matches = 0;
-    uint32_t spill_shifts = 0;
-    while (matches != (vmap_offset + 1)) {
-      DCHECK_NE(spill_mask, 0u);
-      matches += spill_mask & 1;  // Add 1 if the low bit is set.
-      spill_mask >>= 1;
-      spill_shifts++;
+  if (cur_quick_frame_ != NULL) {
+    DCHECK(context_ != NULL); // You can't reliably read registers without a context.
+    DCHECK(m == GetMethod());
+    uint32_t core_spills = m->GetCoreSpillMask();
+    const VmapTable vmap_table(m->GetVmapTableRaw());
+    uint32_t vmap_offset;
+    // TODO: IsInContext stops before spotting floating point registers.
+    if (vmap_table.IsInContext(vreg, vmap_offset)) {
+      // Compute the register we need to load from the context.
+      uint32_t spill_mask = core_spills;
+      CHECK_LT(vmap_offset, static_cast<uint32_t>(__builtin_popcount(spill_mask)));
+      uint32_t matches = 0;
+      uint32_t spill_shifts = 0;
+      while (matches != (vmap_offset + 1)) {
+        DCHECK_NE(spill_mask, 0u);
+        matches += spill_mask & 1;  // Add 1 if the low bit is set.
+        spill_mask >>= 1;
+        spill_shifts++;
+      }
+      spill_shifts--;  // Wind back one as we want the last match.
+      return GetGPR(spill_shifts);
+    } else {
+      const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
+      DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions?
+      uint32_t fp_spills = m->GetFpSpillMask();
+      size_t frame_size = m->GetFrameSizeInBytes();
+      return GetVReg(cur_quick_frame_, code_item, core_spills, fp_spills, frame_size, vreg);
     }
-    spill_shifts--;  // Wind back one as we want the last match.
-    return GetGPR(spill_shifts);
   } else {
-    const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
-    DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions?
-    uint32_t fp_spills = m->GetFpSpillMask();
-    size_t frame_size = m->GetFrameSizeInBytes();
-    return GetVReg(code_item, core_spills, fp_spills, frame_size, vreg);
+    LOG(FATAL) << "Unimplemented - shadow frame GetVReg";
+    return 0;  // Keep GCC happy.
   }
 }
 
 void StackVisitor::SetVReg(Method* m, int vreg, uint32_t new_value) {
-  DCHECK(context_ != NULL); // You can't reliably write registers without a context.
-  DCHECK(m == GetMethod());
-  const VmapTable vmap_table(m->GetVmapTableRaw());
-  uint32_t vmap_offset;
-  // TODO: IsInContext stops before spotting floating point registers.
-  if (vmap_table.IsInContext(vreg, vmap_offset)) {
-    UNIMPLEMENTED(FATAL);
+  if (cur_quick_frame_ != NULL) {
+    DCHECK(context_ != NULL); // You can't reliably write registers without a context.
+    DCHECK(m == GetMethod());
+    const VmapTable vmap_table(m->GetVmapTableRaw());
+    uint32_t vmap_offset;
+    // TODO: IsInContext stops before spotting floating point registers.
+    if (vmap_table.IsInContext(vreg, vmap_offset)) {
+      UNIMPLEMENTED(FATAL);
+    }
+    const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
+    DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions?
+    uint32_t core_spills = m->GetCoreSpillMask();
+    uint32_t fp_spills = m->GetFpSpillMask();
+    size_t frame_size = m->GetFrameSizeInBytes();
+    int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
+    byte* vreg_addr = reinterpret_cast<byte*>(GetCurrentQuickFrame()) + offset;
+    *reinterpret_cast<uint32_t*>(vreg_addr) = new_value;
+  } else {
+    LOG(FATAL) << "Unimplemented - shadow frame SetVReg";
   }
-  const DexFile::CodeItem* code_item = MethodHelper(m).GetCodeItem();
-  DCHECK(code_item != NULL) << PrettyMethod(m); // Can't be NULL or how would we compile its instructions?
-  uint32_t core_spills = m->GetCoreSpillMask();
-  uint32_t fp_spills = m->GetFpSpillMask();
-  size_t frame_size = m->GetFrameSizeInBytes();
-  int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
-  byte* vreg_addr = reinterpret_cast<byte*>(GetCurrentQuickFrame()) + offset;
-  *reinterpret_cast<uint32_t*>(vreg_addr) = new_value;
 }
 
 uintptr_t StackVisitor::GetGPR(uint32_t reg) const {
+  DCHECK (cur_quick_frame_ != NULL) << "This is a quick frame routine";
   return context_->GetGPR(reg);
 }
 
diff --git a/src/stack.h b/src/stack.h
index 254451d..fb0bc48 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -280,10 +280,11 @@
 
   uintptr_t GetGPR(uint32_t reg) const;
 
-  uint32_t GetVReg(const DexFile::CodeItem* code_item, uint32_t core_spills,
-                   uint32_t fp_spills, size_t frame_size, int vreg) const {
+  uint32_t GetVReg(Method** cur_quick_frame, const DexFile::CodeItem* code_item,
+                   uint32_t core_spills, uint32_t fp_spills, size_t frame_size, int vreg) const {
     int offset = GetVRegOffset(code_item, core_spills, fp_spills, frame_size, vreg);
-    byte* vreg_addr = reinterpret_cast<byte*>(GetCurrentQuickFrame()) + offset;
+    DCHECK_EQ(cur_quick_frame, GetCurrentQuickFrame());
+    byte* vreg_addr = reinterpret_cast<byte*>(cur_quick_frame) + offset;
     return *reinterpret_cast<uint32_t*>(vreg_addr);
   }
 
diff --git a/src/thread.cc b/src/thread.cc
index 53942d9..0707c74 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1650,6 +1650,8 @@
         // For all dex registers in the bitmap
         size_t num_regs = std::min(map.RegWidth() * 8,
                                    static_cast<size_t>(code_item->registers_size_));
+        Method** cur_quick_frame = GetCurrentQuickFrame();
+        DCHECK(cur_quick_frame != NULL);
         for (size_t reg = 0; reg < num_regs; ++reg) {
           // Does this register hold a reference?
           if (TestBitmap(reg, reg_bitmap)) {
@@ -1670,8 +1672,8 @@
               spill_shifts--;  // wind back one as we want the last match
               ref = reinterpret_cast<Object*>(GetGPR(spill_shifts));
             } else {
-              ref = reinterpret_cast<Object*>(GetVReg(code_item, core_spills, fp_spills,
-                                                      frame_size, reg));
+              ref = reinterpret_cast<Object*>(GetVReg(cur_quick_frame, code_item, core_spills,
+                                                      fp_spills, frame_size, reg));
             }
             if (ref != NULL) {
               root_visitor_(ref, arg_);