From 41af5e50d0b5e9d13084a61cfe9dfa6b6e201a40 Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Wed, 28 Oct 2015 11:10:46 -0700 Subject: [PATCH] Store method as ArtMethod* instead of jmethodId in Breakpoint Previously we needed a ScopedObjectAccess for Dbg::VisitRoots, this could cause deadlocks in the following scenario: GC: Goes to runnable state while holding mutator lock as shared held. This occurred in Dbg::VisitRoots when calling Breakpoint::Method. Other thread: Calls SuspendAll and suspends the GC thread before it can go back to suspended thread state. This thread then attempts to exclusive lock mutator lock, but the GC is suspended while holding it in a shared state. Bug: 25336094 Change-Id: Idcb8d34c314b1d6951abe533a0cfa586cc07d7d6 --- runtime/debugger.cc | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/runtime/debugger.cc b/runtime/debugger.cc index b17b76e2e..7117be9a5 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -69,29 +69,26 @@ static uint16_t CappedAllocRecordCount(size_t alloc_record_count) { return alloc_record_count; } -class Breakpoint { +class Breakpoint : public ValueObject { public: - Breakpoint(ArtMethod* method, uint32_t dex_pc, - DeoptimizationRequest::Kind deoptimization_kind) - SHARED_REQUIRES(Locks::mutator_lock_) - : method_(nullptr), dex_pc_(dex_pc), deoptimization_kind_(deoptimization_kind) { + Breakpoint(ArtMethod* method, uint32_t dex_pc, DeoptimizationRequest::Kind deoptimization_kind) + : method_(method), + dex_pc_(dex_pc), + deoptimization_kind_(deoptimization_kind) { CHECK(deoptimization_kind_ == DeoptimizationRequest::kNothing || deoptimization_kind_ == DeoptimizationRequest::kSelectiveDeoptimization || deoptimization_kind_ == DeoptimizationRequest::kFullDeoptimization); - ScopedObjectAccessUnchecked soa(Thread::Current()); - method_ = soa.EncodeMethod(method); } Breakpoint(const Breakpoint& other) SHARED_REQUIRES(Locks::mutator_lock_) - : method_(nullptr), dex_pc_(other.dex_pc_), - deoptimization_kind_(other.deoptimization_kind_) { - ScopedObjectAccessUnchecked soa(Thread::Current()); - method_ = soa.EncodeMethod(other.Method()); - } + : method_(other.method_), + dex_pc_(other.dex_pc_), + deoptimization_kind_(other.deoptimization_kind_) {} - ArtMethod* Method() const SHARED_REQUIRES(Locks::mutator_lock_) { - ScopedObjectAccessUnchecked soa(Thread::Current()); - return soa.DecodeMethod(method_); + // Method() is called from root visiting, do not use ScopedObjectAccess here or it can cause + // GC to deadlock if another thread tries to call SuspendAll while the GC is in a runnable state. + ArtMethod* Method() const { + return method_; } uint32_t DexPc() const { @@ -104,7 +101,7 @@ class Breakpoint { private: // The location of this breakpoint. - jmethodID method_; + ArtMethod* method_; uint32_t dex_pc_; // Indicates whether breakpoint needs full deoptimization or selective deoptimization. -- 2.11.0