diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/monitor.cc | 56 | ||||
| -rw-r--r-- | src/stack.cc | 88 | ||||
| -rw-r--r-- | src/stack.h | 7 | ||||
| -rw-r--r-- | src/thread.cc | 6 |
4 files changed, 88 insertions, 69 deletions
diff --git a/src/monitor.cc b/src/monitor.cc index a7d08bce2a..149babf0b2 100644 --- a/src/monitor.cc +++ b/src/monitor.cc @@ -915,34 +915,40 @@ void Monitor::DescribeLocks(std::ostream& os, StackVisitor* stack_visitor) { 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); + // 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; + } - 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]; + // 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); + } - // 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); } - - 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 67b9bfa1a8..dd319bc0af 100644 --- a/src/stack.cc +++ b/src/stack.cc @@ -106,55 +106,65 @@ uint32_t StackVisitor::GetDexPc() const { } 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 254451d71e..fb0bc486b7 100644 --- a/src/stack.h +++ b/src/stack.h @@ -280,10 +280,11 @@ class StackVisitor { 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 53942d9702..0707c74eff 100644 --- a/src/thread.cc +++ b/src/thread.cc @@ -1650,6 +1650,8 @@ class ReferenceMapVisitor : public StackVisitor { // 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 @@ class ReferenceMapVisitor : public StackVisitor { 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_); |