From a5eae69589ff562ad66c57665882cd16f237321c Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Wed, 17 Dec 2014 17:56:03 -0800 Subject: Add heap task processor The heap task processor processes async tasks which may be delayed. The motivation for this change is preventing deadlocks which can occur when the daemon threads get suspended by GetThreadStack. Other improvements, reduces daemon thread count by one. Cleaner pending transition VS heap trimming logic. Bug: 18739541 Change-Id: Idab52b2d9661a6385cada74b93ff297ddc55fc78 --- runtime/gc/reference_processor.cc | 43 ++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) (limited to 'runtime/gc/reference_processor.cc') diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc index 99bd63fa8a..01e8795669 100644 --- a/runtime/gc/reference_processor.cc +++ b/runtime/gc/reference_processor.cc @@ -23,11 +23,14 @@ #include "reflection.h" #include "ScopedLocalRef.h" #include "scoped_thread_state_change.h" +#include "task_processor.h" #include "well_known_classes.h" namespace art { namespace gc { +static constexpr bool kAsyncReferenceQueueAdd = false; + ReferenceProcessor::ReferenceProcessor() : process_references_args_(nullptr, nullptr, nullptr), preserving_references_(false), @@ -213,17 +216,43 @@ void ReferenceProcessor::UpdateRoots(IsMarkedCallback* callback, void* arg) { cleared_references_.UpdateRoots(callback, arg); } +class ClearedReferenceTask : public HeapTask { + public: + explicit ClearedReferenceTask(jobject cleared_references) + : HeapTask(NanoTime()), cleared_references_(cleared_references) { + } + virtual void Run(Thread* thread) { + ScopedObjectAccess soa(thread); + jvalue args[1]; + args[0].l = cleared_references_; + InvokeWithJValues(soa, nullptr, WellKnownClasses::java_lang_ref_ReferenceQueue_add, args); + soa.Env()->DeleteGlobalRef(cleared_references_); + } + + private: + const jobject cleared_references_; +}; + void ReferenceProcessor::EnqueueClearedReferences(Thread* self) { Locks::mutator_lock_->AssertNotHeld(self); + // When a runtime isn't started there are no reference queues to care about so ignore. if (!cleared_references_.IsEmpty()) { - // When a runtime isn't started there are no reference queues to care about so ignore. if (LIKELY(Runtime::Current()->IsStarted())) { - ScopedObjectAccess soa(self); - ScopedLocalRef arg(self->GetJniEnv(), - soa.AddLocalReference(cleared_references_.GetList())); - jvalue args[1]; - args[0].l = arg.get(); - InvokeWithJValues(soa, nullptr, WellKnownClasses::java_lang_ref_ReferenceQueue_add, args); + jobject cleared_references; + { + ReaderMutexLock mu(self, *Locks::mutator_lock_); + cleared_references = self->GetJniEnv()->vm->AddGlobalRef( + self, cleared_references_.GetList()); + } + if (kAsyncReferenceQueueAdd) { + // TODO: This can cause RunFinalization to terminate before newly freed objects are + // finalized since they may not be enqueued by the time RunFinalization starts. + Runtime::Current()->GetHeap()->GetTaskProcessor()->AddTask( + self, new ClearedReferenceTask(cleared_references)); + } else { + ClearedReferenceTask task(cleared_references); + task.Run(self); + } } cleared_references_.Clear(); } -- cgit v1.2.3-59-g8ed1b