blob: 49446399fdd48c6fce9ddac27cd35f60470e7df3 [file] [log] [blame]
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "reference_processor.h"
18
Vladimir Marko6834d342018-05-25 13:12:09 +010019#include "art_field-inl.h"
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080020#include "base/mutex.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010021#include "base/time_utils.h"
David Sehrc431b9d2018-03-02 12:01:51 -080022#include "base/utils.h"
Vladimir Marko6834d342018-05-25 13:12:09 +010023#include "class_root.h"
Mathieu Chartier97509952015-07-13 14:35:43 -070024#include "collector/garbage_collector.h"
Vladimir Markoa3ad0cd2018-05-04 10:06:38 +010025#include "jni/java_vm_ext.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070026#include "mirror/class-inl.h"
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -070027#include "mirror/object-inl.h"
28#include "mirror/reference-inl.h"
Andreas Gampe373a9b52017-10-18 09:01:57 -070029#include "nativehelper/scoped_local_ref.h"
Andreas Gampe5d08fcc2017-06-05 17:56:46 -070030#include "object_callbacks.h"
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -070031#include "reflection.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070032#include "scoped_thread_state_change-inl.h"
Mathieu Chartiera5eae692014-12-17 17:56:03 -080033#include "task_processor.h"
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -070034#include "well_known_classes.h"
35
36namespace art {
37namespace gc {
38
Mathieu Chartiera5eae692014-12-17 17:56:03 -080039static constexpr bool kAsyncReferenceQueueAdd = false;
40
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -070041ReferenceProcessor::ReferenceProcessor()
Mathieu Chartier97509952015-07-13 14:35:43 -070042 : collector_(nullptr),
Mathieu Chartiera5a53ef2014-09-12 12:58:05 -070043 preserving_references_(false),
44 condition_("reference processor condition", *Locks::reference_processor_lock_) ,
45 soft_reference_queue_(Locks::reference_queue_soft_references_lock_),
46 weak_reference_queue_(Locks::reference_queue_weak_references_lock_),
47 finalizer_reference_queue_(Locks::reference_queue_finalizer_references_lock_),
48 phantom_reference_queue_(Locks::reference_queue_phantom_references_lock_),
49 cleared_references_(Locks::reference_queue_cleared_references_lock_) {
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -070050}
51
Vladimir Marko6834d342018-05-25 13:12:09 +010052static inline MemberOffset GetSlowPathFlagOffset(ObjPtr<mirror::Class> reference_class)
53 REQUIRES_SHARED(Locks::mutator_lock_) {
54 DCHECK(reference_class == GetClassRoot<mirror::Reference>());
55 // Second static field
56 ArtField* field = reference_class->GetStaticField(1);
57 DCHECK_STREQ(field->GetName(), "slowPathEnabled");
58 return field->GetOffset();
59}
60
61static inline void SetSlowPathFlag(bool enabled) REQUIRES_SHARED(Locks::mutator_lock_) {
62 ObjPtr<mirror::Class> reference_class = GetClassRoot<mirror::Reference>();
63 MemberOffset slow_path_offset = GetSlowPathFlagOffset(reference_class);
Andreas Gampe98ea9d92018-10-19 14:06:15 -070064 reference_class->SetFieldBoolean</* kTransactionActive= */ false, /* kCheckTransaction= */ false>(
Vladimir Marko6834d342018-05-25 13:12:09 +010065 slow_path_offset, enabled ? 1 : 0);
66}
67
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -070068void ReferenceProcessor::EnableSlowPath() {
Andreas Gampe98ea9d92018-10-19 14:06:15 -070069 SetSlowPathFlag(/* enabled= */ true);
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -070070}
71
72void ReferenceProcessor::DisableSlowPath(Thread* self) {
Andreas Gampe98ea9d92018-10-19 14:06:15 -070073 SetSlowPathFlag(/* enabled= */ false);
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -070074 condition_.Broadcast(self);
75}
76
Vladimir Marko6834d342018-05-25 13:12:09 +010077bool ReferenceProcessor::SlowPathEnabled() {
78 ObjPtr<mirror::Class> reference_class = GetClassRoot<mirror::Reference>();
79 MemberOffset slow_path_offset = GetSlowPathFlagOffset(reference_class);
80 return reference_class->GetFieldBoolean(slow_path_offset);
81}
82
Hiroshi Yamauchi0b713572015-06-16 18:29:23 -070083void ReferenceProcessor::BroadcastForSlowPath(Thread* self) {
Hiroshi Yamauchi0b713572015-06-16 18:29:23 -070084 MutexLock mu(self, *Locks::reference_processor_lock_);
85 condition_.Broadcast(self);
86}
87
Mathieu Chartier5d3f73a2016-10-14 14:28:47 -070088ObjPtr<mirror::Object> ReferenceProcessor::GetReferent(Thread* self,
89 ObjPtr<mirror::Reference> reference) {
Hiroshi Yamauchi0b713572015-06-16 18:29:23 -070090 if (!kUseReadBarrier || self->GetWeakRefAccessEnabled()) {
91 // Under read barrier / concurrent copying collector, it's not safe to call GetReferent() when
92 // weak ref access is disabled as the call includes a read barrier which may push a ref onto the
93 // mark stack and interfere with termination of marking.
Mathieu Chartier5d3f73a2016-10-14 14:28:47 -070094 ObjPtr<mirror::Object> const referent = reference->GetReferent();
Hiroshi Yamauchi0b713572015-06-16 18:29:23 -070095 // If the referent is null then it is already cleared, we can just return null since there is no
96 // scenario where it becomes non-null during the reference processing phase.
97 if (UNLIKELY(!SlowPathEnabled()) || referent == nullptr) {
98 return referent;
99 }
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700100 }
Mathieu Chartiera5a53ef2014-09-12 12:58:05 -0700101 MutexLock mu(self, *Locks::reference_processor_lock_);
Hiroshi Yamauchi0b713572015-06-16 18:29:23 -0700102 while ((!kUseReadBarrier && SlowPathEnabled()) ||
103 (kUseReadBarrier && !self->GetWeakRefAccessEnabled())) {
Mathieu Chartier36994ba2016-12-13 11:46:28 -0800104 ObjPtr<mirror::Object> referent = reference->GetReferent<kWithoutReadBarrier>();
Mathieu Chartier308351a2014-06-15 12:39:02 -0700105 // If the referent became cleared, return it. Don't need barrier since thread roots can't get
106 // updated until after we leave the function due to holding the mutator lock.
Mathieu Chartier36994ba2016-12-13 11:46:28 -0800107 if (referent == nullptr) {
Mathieu Chartier2175f522014-05-09 11:01:06 -0700108 return nullptr;
109 }
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700110 // Try to see if the referent is already marked by using the is_marked_callback. We can return
Mathieu Chartier308351a2014-06-15 12:39:02 -0700111 // it to the mutator as long as the GC is not preserving references.
Mathieu Chartier97509952015-07-13 14:35:43 -0700112 if (LIKELY(collector_ != nullptr)) {
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700113 // If it's null it means not marked, but it could become marked if the referent is reachable
Roland Levillain91d65e02016-01-19 15:59:16 +0000114 // by finalizer referents. So we cannot return in this case and must block. Otherwise, we
Fred Shih530e1b52014-06-09 15:19:54 -0700115 // can return it to the mutator as long as the GC is not preserving references, in which
116 // case only black nodes can be safely returned. If the GC is preserving references, the
117 // mutator could take a white field from a grey or white node and move it somewhere else
118 // in the heap causing corruption since this field would get swept.
Mathieu Chartier36994ba2016-12-13 11:46:28 -0800119 // Use the cached referent instead of calling GetReferent since other threads could call
120 // Reference.clear() after we did the null check resulting in a null pointer being
121 // incorrectly passed to IsMarked. b/33569625
122 ObjPtr<mirror::Object> forwarded_ref = collector_->IsMarked(referent.Ptr());
123 if (forwarded_ref != nullptr) {
124 // Non null means that it is marked.
Fred Shih530e1b52014-06-09 15:19:54 -0700125 if (!preserving_references_ ||
Richard Uhlerc4695df2016-01-15 14:08:05 -0800126 (LIKELY(!reference->IsFinalizerReferenceInstance()) && reference->IsUnprocessed())) {
Mathieu Chartier36994ba2016-12-13 11:46:28 -0800127 return forwarded_ref;
Fred Shih530e1b52014-06-09 15:19:54 -0700128 }
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700129 }
130 }
Hiroshi Yamauchi30493242016-11-03 13:06:52 -0700131 // Check and run the empty checkpoint before blocking so the empty checkpoint will work in the
132 // presence of threads blocking for weak ref access.
Hiroshi Yamauchia2224042017-02-08 16:35:45 -0800133 self->CheckEmptyCheckpointFromWeakRefAccess(Locks::reference_processor_lock_);
Mathieu Chartier2d1ab0a2014-05-08 15:27:31 -0700134 condition_.WaitHoldingLocks(self);
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700135 }
136 return reference->GetReferent();
137}
138
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700139void ReferenceProcessor::StartPreservingReferences(Thread* self) {
Mathieu Chartiera5a53ef2014-09-12 12:58:05 -0700140 MutexLock mu(self, *Locks::reference_processor_lock_);
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700141 preserving_references_ = true;
142}
143
144void ReferenceProcessor::StopPreservingReferences(Thread* self) {
Mathieu Chartiera5a53ef2014-09-12 12:58:05 -0700145 MutexLock mu(self, *Locks::reference_processor_lock_);
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700146 preserving_references_ = false;
147 // We are done preserving references, some people who are blocked may see a marked referent.
148 condition_.Broadcast(self);
149}
150
151// Process reference class instances and schedule finalizations.
Mathieu Chartier5d3f73a2016-10-14 14:28:47 -0700152void ReferenceProcessor::ProcessReferences(bool concurrent,
153 TimingLogger* timings,
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700154 bool clear_soft_references,
Mathieu Chartier97509952015-07-13 14:35:43 -0700155 collector::GarbageCollector* collector) {
Mathieu Chartierf5997b42014-06-20 10:37:54 -0700156 TimingLogger::ScopedTiming t(concurrent ? __FUNCTION__ : "(Paused)ProcessReferences", timings);
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700157 Thread* self = Thread::Current();
158 {
Mathieu Chartiera5a53ef2014-09-12 12:58:05 -0700159 MutexLock mu(self, *Locks::reference_processor_lock_);
Mathieu Chartier97509952015-07-13 14:35:43 -0700160 collector_ = collector;
Hiroshi Yamauchi0b713572015-06-16 18:29:23 -0700161 if (!kUseReadBarrier) {
162 CHECK_EQ(SlowPathEnabled(), concurrent) << "Slow path must be enabled iff concurrent";
163 } else {
164 // Weak ref access is enabled at Zygote compaction by SemiSpace (concurrent == false).
165 CHECK_EQ(!self->GetWeakRefAccessEnabled(), concurrent);
166 }
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700167 }
Hiroshi Yamauchi057d9772017-02-17 15:33:23 -0800168 if (kIsDebugBuild && collector->IsTransactionActive()) {
169 // In transaction mode, we shouldn't enqueue any Reference to the queues.
170 // See DelayReferenceReferent().
171 DCHECK(soft_reference_queue_.IsEmpty());
172 DCHECK(weak_reference_queue_.IsEmpty());
173 DCHECK(finalizer_reference_queue_.IsEmpty());
174 DCHECK(phantom_reference_queue_.IsEmpty());
175 }
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700176 // Unless required to clear soft references with white references, preserve some white referents.
177 if (!clear_soft_references) {
Mathieu Chartierf5997b42014-06-20 10:37:54 -0700178 TimingLogger::ScopedTiming split(concurrent ? "ForwardSoftReferences" :
Fred Shih530e1b52014-06-09 15:19:54 -0700179 "(Paused)ForwardSoftReferences", timings);
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700180 if (concurrent) {
181 StartPreservingReferences(self);
182 }
Mathieu Chartier81187812015-07-15 14:24:07 -0700183 // TODO: Add smarter logic for preserving soft references. The behavior should be a conditional
184 // mark if the SoftReference is supposed to be preserved.
Mathieu Chartier97509952015-07-13 14:35:43 -0700185 soft_reference_queue_.ForwardSoftReferences(collector);
186 collector->ProcessMarkStack();
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700187 if (concurrent) {
188 StopPreservingReferences(self);
189 }
190 }
191 // Clear all remaining soft and weak references with white referents.
Mathieu Chartier97509952015-07-13 14:35:43 -0700192 soft_reference_queue_.ClearWhiteReferences(&cleared_references_, collector);
193 weak_reference_queue_.ClearWhiteReferences(&cleared_references_, collector);
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700194 {
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800195 TimingLogger::ScopedTiming t2(concurrent ? "EnqueueFinalizerReferences" :
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700196 "(Paused)EnqueueFinalizerReferences", timings);
197 if (concurrent) {
198 StartPreservingReferences(self);
199 }
200 // Preserve all white objects with finalize methods and schedule them for finalization.
Mathieu Chartier97509952015-07-13 14:35:43 -0700201 finalizer_reference_queue_.EnqueueFinalizerReferences(&cleared_references_, collector);
202 collector->ProcessMarkStack();
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700203 if (concurrent) {
204 StopPreservingReferences(self);
205 }
206 }
207 // Clear all finalizer referent reachable soft and weak references with white referents.
Mathieu Chartier97509952015-07-13 14:35:43 -0700208 soft_reference_queue_.ClearWhiteReferences(&cleared_references_, collector);
209 weak_reference_queue_.ClearWhiteReferences(&cleared_references_, collector);
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700210 // Clear all phantom references with white referents.
Mathieu Chartier97509952015-07-13 14:35:43 -0700211 phantom_reference_queue_.ClearWhiteReferences(&cleared_references_, collector);
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700212 // At this point all reference queues other than the cleared references should be empty.
213 DCHECK(soft_reference_queue_.IsEmpty());
214 DCHECK(weak_reference_queue_.IsEmpty());
215 DCHECK(finalizer_reference_queue_.IsEmpty());
216 DCHECK(phantom_reference_queue_.IsEmpty());
Mathieu Chartier2175f522014-05-09 11:01:06 -0700217 {
Mathieu Chartiera5a53ef2014-09-12 12:58:05 -0700218 MutexLock mu(self, *Locks::reference_processor_lock_);
Mathieu Chartier2175f522014-05-09 11:01:06 -0700219 // Need to always do this since the next GC may be concurrent. Doing this for only concurrent
220 // could result in a stale is_marked_callback_ being called before the reference processing
221 // starts since there is a small window of time where slow_path_enabled_ is enabled but the
222 // callback isn't yet set.
Mathieu Chartier97509952015-07-13 14:35:43 -0700223 collector_ = nullptr;
224 if (!kUseReadBarrier && concurrent) {
225 // Done processing, disable the slow path and broadcast to the waiters.
226 DisableSlowPath(self);
Mathieu Chartier2175f522014-05-09 11:01:06 -0700227 }
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700228 }
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700229}
230
231// Process the "referent" field in a java.lang.ref.Reference. If the referent has not yet been
232// marked, put it on the appropriate list in the heap for later processing.
Mathieu Chartier5d3f73a2016-10-14 14:28:47 -0700233void ReferenceProcessor::DelayReferenceReferent(ObjPtr<mirror::Class> klass,
234 ObjPtr<mirror::Reference> ref,
Mathieu Chartier97509952015-07-13 14:35:43 -0700235 collector::GarbageCollector* collector) {
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700236 // klass can be the class of the old object if the visitor already updated the class of ref.
Mathieu Chartier308351a2014-06-15 12:39:02 -0700237 DCHECK(klass != nullptr);
Fred Shih4ee7a662014-07-11 09:59:27 -0700238 DCHECK(klass->IsTypeOfReferenceClass());
Mathieu Chartier308351a2014-06-15 12:39:02 -0700239 mirror::HeapReference<mirror::Object>* referent = ref->GetReferentReferenceAddr();
Hiroshi Yamauchi65f5f242016-12-19 11:44:47 -0800240 // do_atomic_update needs to be true because this happens outside of the reference processing
241 // phase.
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700242 if (!collector->IsNullOrMarkedHeapReference(referent, /*do_atomic_update=*/true)) {
Hiroshi Yamauchi057d9772017-02-17 15:33:23 -0800243 if (UNLIKELY(collector->IsTransactionActive())) {
244 // In transaction mode, keep the referent alive and avoid any reference processing to avoid the
245 // issue of rolling back reference processing. do_atomic_update needs to be true because this
246 // happens outside of the reference processing phase.
247 if (!referent->IsNull()) {
Andreas Gampe98ea9d92018-10-19 14:06:15 -0700248 collector->MarkHeapReference(referent, /*do_atomic_update=*/ true);
Hiroshi Yamauchi057d9772017-02-17 15:33:23 -0800249 }
250 return;
251 }
Mathieu Chartier308351a2014-06-15 12:39:02 -0700252 Thread* self = Thread::Current();
253 // TODO: Remove these locks, and use atomic stacks for storing references?
254 // We need to check that the references haven't already been enqueued since we can end up
255 // scanning the same reference multiple times due to dirty cards.
256 if (klass->IsSoftReferenceClass()) {
257 soft_reference_queue_.AtomicEnqueueIfNotEnqueued(self, ref);
258 } else if (klass->IsWeakReferenceClass()) {
259 weak_reference_queue_.AtomicEnqueueIfNotEnqueued(self, ref);
260 } else if (klass->IsFinalizerReferenceClass()) {
261 finalizer_reference_queue_.AtomicEnqueueIfNotEnqueued(self, ref);
262 } else if (klass->IsPhantomReferenceClass()) {
263 phantom_reference_queue_.AtomicEnqueueIfNotEnqueued(self, ref);
264 } else {
David Sehr709b0702016-10-13 09:12:37 -0700265 LOG(FATAL) << "Invalid reference type " << klass->PrettyClass() << " " << std::hex
Mathieu Chartier308351a2014-06-15 12:39:02 -0700266 << klass->GetAccessFlags();
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700267 }
268 }
269}
270
Mathieu Chartier97509952015-07-13 14:35:43 -0700271void ReferenceProcessor::UpdateRoots(IsMarkedVisitor* visitor) {
272 cleared_references_.UpdateRoots(visitor);
Mathieu Chartier52e4b432014-06-10 11:22:31 -0700273}
274
Mathieu Chartiera5eae692014-12-17 17:56:03 -0800275class ClearedReferenceTask : public HeapTask {
276 public:
277 explicit ClearedReferenceTask(jobject cleared_references)
278 : HeapTask(NanoTime()), cleared_references_(cleared_references) {
279 }
Andreas Gampefa6a1b02018-09-07 08:11:55 -0700280 void Run(Thread* thread) override {
Mathieu Chartiera5eae692014-12-17 17:56:03 -0800281 ScopedObjectAccess soa(thread);
282 jvalue args[1];
283 args[0].l = cleared_references_;
284 InvokeWithJValues(soa, nullptr, WellKnownClasses::java_lang_ref_ReferenceQueue_add, args);
285 soa.Env()->DeleteGlobalRef(cleared_references_);
286 }
287
288 private:
289 const jobject cleared_references_;
290};
291
Mathieu Chartier308351a2014-06-15 12:39:02 -0700292void ReferenceProcessor::EnqueueClearedReferences(Thread* self) {
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700293 Locks::mutator_lock_->AssertNotHeld(self);
Mathieu Chartiera5eae692014-12-17 17:56:03 -0800294 // When a runtime isn't started there are no reference queues to care about so ignore.
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700295 if (!cleared_references_.IsEmpty()) {
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700296 if (LIKELY(Runtime::Current()->IsStarted())) {
Mathieu Chartiera5eae692014-12-17 17:56:03 -0800297 jobject cleared_references;
298 {
299 ReaderMutexLock mu(self, *Locks::mutator_lock_);
Ian Rogers55256cb2017-12-21 17:07:11 -0800300 cleared_references = self->GetJniEnv()->GetVm()->AddGlobalRef(
Mathieu Chartiera5eae692014-12-17 17:56:03 -0800301 self, cleared_references_.GetList());
302 }
303 if (kAsyncReferenceQueueAdd) {
304 // TODO: This can cause RunFinalization to terminate before newly freed objects are
305 // finalized since they may not be enqueued by the time RunFinalization starts.
306 Runtime::Current()->GetHeap()->GetTaskProcessor()->AddTask(
307 self, new ClearedReferenceTask(cleared_references));
308 } else {
309 ClearedReferenceTask task(cleared_references);
310 task.Run(self);
311 }
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700312 }
313 cleared_references_.Clear();
314 }
315}
316
Mathieu Chartierc9a70282016-12-13 14:44:33 -0800317void ReferenceProcessor::ClearReferent(ObjPtr<mirror::Reference> ref) {
Mathieu Chartiera5a53ef2014-09-12 12:58:05 -0700318 Thread* self = Thread::Current();
319 MutexLock mu(self, *Locks::reference_processor_lock_);
Mathieu Chartierc9a70282016-12-13 14:44:33 -0800320 // Need to wait until reference processing is done since IsMarkedHeapReference does not have a
321 // CAS. If we do not wait, it can result in the GC un-clearing references due to race conditions.
322 // This also handles the race where the referent gets cleared after a null check but before
323 // IsMarkedHeapReference is called.
324 WaitUntilDoneProcessingReferences(self);
325 if (Runtime::Current()->IsActiveTransaction()) {
326 ref->ClearReferent<true>();
327 } else {
328 ref->ClearReferent<false>();
329 }
330}
331
332void ReferenceProcessor::WaitUntilDoneProcessingReferences(Thread* self) {
333 // Wait until we are done processing reference.
Hiroshi Yamauchi0b713572015-06-16 18:29:23 -0700334 while ((!kUseReadBarrier && SlowPathEnabled()) ||
335 (kUseReadBarrier && !self->GetWeakRefAccessEnabled())) {
Hiroshi Yamauchi30493242016-11-03 13:06:52 -0700336 // Check and run the empty checkpoint before blocking so the empty checkpoint will work in the
337 // presence of threads blocking for weak ref access.
Hiroshi Yamauchia2224042017-02-08 16:35:45 -0800338 self->CheckEmptyCheckpointFromWeakRefAccess(Locks::reference_processor_lock_);
Pavel Vyssotskid64ba382014-12-15 18:00:17 +0600339 condition_.WaitHoldingLocks(self);
Mathieu Chartiera5a53ef2014-09-12 12:58:05 -0700340 }
Mathieu Chartierc9a70282016-12-13 14:44:33 -0800341}
342
343bool ReferenceProcessor::MakeCircularListIfUnenqueued(
344 ObjPtr<mirror::FinalizerReference> reference) {
345 Thread* self = Thread::Current();
346 MutexLock mu(self, *Locks::reference_processor_lock_);
347 WaitUntilDoneProcessingReferences(self);
Mathieu Chartiera5a53ef2014-09-12 12:58:05 -0700348 // At this point, since the sentinel of the reference is live, it is guaranteed to not be
349 // enqueued if we just finished processing references. Otherwise, we may be doing the main GC
350 // phase. Since we are holding the reference processor lock, it guarantees that reference
351 // processing can't begin. The GC could have just enqueued the reference one one of the internal
352 // GC queues, but since we hold the lock finalizer_reference_queue_ lock it also prevents this
353 // race.
354 MutexLock mu2(self, *Locks::reference_queue_finalizer_references_lock_);
Richard Uhlerc4695df2016-01-15 14:08:05 -0800355 if (reference->IsUnprocessed()) {
Mathieu Chartiera5a53ef2014-09-12 12:58:05 -0700356 CHECK(reference->IsFinalizerReferenceInstance());
Richard Uhler522d51b2016-01-22 14:18:57 -0800357 reference->SetPendingNext(reference);
Mathieu Chartiera5a53ef2014-09-12 12:58:05 -0700358 return true;
359 }
360 return false;
361}
362
Mathieu Chartier78f7b4c2014-05-06 10:57:27 -0700363} // namespace gc
364} // namespace art