From bb43b433c845e253a11346f0f03706d58a44f23c Mon Sep 17 00:00:00 2001 From: Sebastien Hertz Date: Mon, 14 Apr 2014 11:59:08 +0200 Subject: [PATCH] Clear unused roots from debugger SingleStepControl and DebugInvokeReq hold roots which are only used during a limited amount of time. Clear these roots once we finish using them. Also cleans some code around single-step. Change-Id: Ica2f65e04a4d60272199490cd40ad1803d3b9f02 --- runtime/debugger.cc | 42 +++++++++++++++++++++++++++++++----------- runtime/debugger.h | 6 ++++++ runtime/thread_list.cc | 2 +- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 514ad4cb3..bcecbc242 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -231,6 +231,14 @@ void DebugInvokeReq::VisitRoots(RootCallback* callback, void* arg, uint32_t tid, } } +void DebugInvokeReq::Clear() { + invoke_needed = false; + receiver = nullptr; + thread = nullptr; + klass = nullptr; + method = nullptr; +} + void SingleStepControl::VisitRoots(RootCallback* callback, void* arg, uint32_t tid, RootType root_type) { if (method != nullptr) { @@ -238,6 +246,16 @@ void SingleStepControl::VisitRoots(RootCallback* callback, void* arg, uint32_t t } } +bool SingleStepControl::ContainsDexPc(uint32_t dex_pc) const { + return dex_pcs.find(dex_pc) == dex_pcs.end(); +} + +void SingleStepControl::Clear() { + is_active = false; + method = nullptr; + dex_pcs.clear(); +} + void DeoptimizationRequest::VisitRoots(RootCallback* callback, void* arg) { if (method != nullptr) { callback(reinterpret_cast(&method), arg, 0, kRootDebugger); @@ -2521,7 +2539,7 @@ void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object, } else if (single_step_control->step_size == JDWP::SS_MIN) { event_flags |= kSingleStep; VLOG(jdwp) << "SS new instruction"; - } else if (single_step_control->dex_pcs.find(dex_pc) == single_step_control->dex_pcs.end()) { + } else if (single_step_control->ContainsDexPc(dex_pc)) { event_flags |= kSingleStep; VLOG(jdwp) << "SS new line"; } @@ -2543,7 +2561,7 @@ void Dbg::UpdateDebugger(Thread* thread, mirror::Object* this_object, if (single_step_control->step_size == JDWP::SS_MIN) { event_flags |= kSingleStep; VLOG(jdwp) << "SS new instruction"; - } else if (single_step_control->dex_pcs.find(dex_pc) == single_step_control->dex_pcs.end()) { + } else if (single_step_control->ContainsDexPc(dex_pc)) { event_flags |= kSingleStep; VLOG(jdwp) << "SS new line"; } @@ -2910,8 +2928,9 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize // struct DebugCallbackContext { - explicit DebugCallbackContext(SingleStepControl* single_step_control, int32_t line_number) - : single_step_control_(single_step_control), line_number_(line_number), + explicit DebugCallbackContext(SingleStepControl* single_step_control, int32_t line_number, + const DexFile::CodeItem* code_item) + : single_step_control_(single_step_control), line_number_(line_number), code_item_(code_item), last_pc_valid(false), last_pc(0) { } @@ -2938,7 +2957,7 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize ~DebugCallbackContext() { // If the line number was the last in the position table... if (last_pc_valid) { - size_t end = MethodHelper(single_step_control_->method).GetCodeItem()->insns_size_in_code_units_; + size_t end = code_item_->insns_size_in_code_units_; for (uint32_t dex_pc = last_pc; dex_pc < end; ++dex_pc) { single_step_control_->dex_pcs.insert(dex_pc); } @@ -2947,15 +2966,17 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize SingleStepControl* const single_step_control_; const int32_t line_number_; + const DexFile::CodeItem* const code_item_; bool last_pc_valid; uint32_t last_pc; }; single_step_control->dex_pcs.clear(); mirror::ArtMethod* m = single_step_control->method; if (!m->IsNative()) { - DebugCallbackContext context(single_step_control, line_number); MethodHelper mh(m); - mh.GetDexFile().DecodeDebugInfo(mh.GetCodeItem(), m->IsStatic(), m->GetDexMethodIndex(), + const DexFile::CodeItem* const code_item = mh.GetCodeItem(); + DebugCallbackContext context(single_step_control, line_number, code_item); + mh.GetDexFile().DecodeDebugInfo(code_item, m->IsStatic(), m->GetDexMethodIndex(), DebugCallbackContext::Callback, NULL, &context); } @@ -2975,8 +2996,8 @@ JDWP::JdwpError Dbg::ConfigureStep(JDWP::ObjectId thread_id, JDWP::JdwpStepSize VLOG(jdwp) << "Single-step current line: " << line_number; VLOG(jdwp) << "Single-step current stack depth: " << single_step_control->stack_depth; VLOG(jdwp) << "Single-step dex_pc values:"; - for (std::set::iterator it = single_step_control->dex_pcs.begin(); it != single_step_control->dex_pcs.end(); ++it) { - VLOG(jdwp) << StringPrintf(" %#x", *it); + for (uint32_t dex_pc : single_step_control->dex_pcs) { + VLOG(jdwp) << StringPrintf(" %#x", dex_pc); } } @@ -2991,8 +3012,7 @@ void Dbg::UnconfigureStep(JDWP::ObjectId thread_id) { if (error == JDWP::ERR_NONE) { SingleStepControl* single_step_control = thread->GetSingleStepControl(); DCHECK(single_step_control != nullptr); - single_step_control->is_active = false; - single_step_control->dex_pcs.clear(); + single_step_control->Clear(); } } diff --git a/runtime/debugger.h b/runtime/debugger.h index 23c9c6a1a..c1c1dd442 100644 --- a/runtime/debugger.h +++ b/runtime/debugger.h @@ -85,6 +85,8 @@ struct DebugInvokeReq { void VisitRoots(RootCallback* callback, void* arg, uint32_t tid, RootType root_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + void Clear(); + private: DISALLOW_COPY_AND_ASSIGN(DebugInvokeReq); }; @@ -118,6 +120,10 @@ struct SingleStepControl { void VisitRoots(RootCallback* callback, void* arg, uint32_t tid, RootType root_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + bool ContainsDexPc(uint32_t dex_pc) const; + + void Clear(); + private: DISALLOW_COPY_AND_ASSIGN(SingleStepControl); }; diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc index 8dad41990..270deb0a9 100644 --- a/runtime/thread_list.cc +++ b/runtime/thread_list.cc @@ -617,7 +617,7 @@ void ThreadList::SuspendSelfForDebugger() { DCHECK(pReq != NULL); if (pReq->invoke_needed) { // Clear this before signaling. - pReq->invoke_needed = false; + pReq->Clear(); VLOG(jdwp) << "invoke complete, signaling"; MutexLock mu(self, pReq->lock); -- 2.11.0