From 530e1b54887b6b5e7d648170096e22a5f1850ea8 Mon Sep 17 00:00:00 2001 From: Fred Shih Date: Mon, 9 Jun 2014 15:19:54 -0700 Subject: Reduced frequency of blocks for concurrent gc Immediately return for references that are marked before reference processing without blocking. Soft references are kept in the queue until the reference processor stops preserving, after which, all marked references are removed. Finalizer references will still block on get(). Bug: 15471830 Change-Id: I588fcaef40b79ed7c95a4aa7f4fc2e17ee0c288f --- runtime/gc/reference_processor.cc | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'runtime/gc/reference_processor.cc') diff --git a/runtime/gc/reference_processor.cc b/runtime/gc/reference_processor.cc index a58df8ec2c..7988af7f6b 100644 --- a/runtime/gc/reference_processor.cc +++ b/runtime/gc/reference_processor.cc @@ -61,15 +61,20 @@ mirror::Object* ReferenceProcessor::GetReferent(Thread* self, mirror::Reference* } // Try to see if the referent is already marked by using the is_marked_callback. We can return // it to the mutator as long as the GC is not preserving references. If the GC is - // preserving references, the mutator could take a white field and move it somewhere else - // in the heap causing corruption since this field would get swept. IsMarkedCallback* const is_marked_callback = process_references_args_.is_marked_callback_; - if (!preserving_references_ && is_marked_callback != nullptr) { + if (LIKELY(is_marked_callback != nullptr)) { mirror::Object* const obj = is_marked_callback(referent, process_references_args_.arg_); // If it's null it means not marked, but it could become marked if the referent is reachable - // by finalizer referents. So we can not return in this case and must block. + // by finalizer referents. So we can not return in this case and must block. Otherwise, we + // can return it to the mutator as long as the GC is not preserving references, in which + // case only black nodes can be safely returned. If the GC is preserving references, the + // mutator could take a white field from a grey or white node and move it somewhere else + // in the heap causing corruption since this field would get swept. if (obj != nullptr) { - return obj; + if (!preserving_references_ || + (LIKELY(!reference->IsFinalizerReferenceInstance()) && !reference->IsEnqueued())) { + return obj; + } } } condition_.WaitHoldingLocks(self); @@ -113,14 +118,14 @@ void ReferenceProcessor::ProcessReferences(bool concurrent, TimingLogger* timing timings->StartSplit(concurrent ? "ProcessReferences" : "(Paused)ProcessReferences"); // Unless required to clear soft references with white references, preserve some white referents. if (!clear_soft_references) { - TimingLogger::ScopedSplit split(concurrent ? "PreserveSomeSoftReferences" : - "(Paused)PreserveSomeSoftReferences", timings); + TimingLogger::ScopedSplit split(concurrent ? "ForwardSoftReferences" : + "(Paused)ForwardSoftReferences", timings); if (concurrent) { StartPreservingReferences(self); } - // References with a marked referent are removed from the list. - soft_reference_queue_.PreserveSomeSoftReferences(&PreserveSoftReferenceCallback, - &process_references_args_); + + soft_reference_queue_.ForwardSoftReferences(&PreserveSoftReferenceCallback, + &process_references_args_); process_mark_stack_callback(arg); if (concurrent) { StopPreservingReferences(self); -- cgit v1.2.3-59-g8ed1b