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_);