1 /*
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
19 #include "art_field-inl.h"
20 #include "base/mutex.h"
21 #include "base/time_utils.h"
22 #include "base/utils.h"
23 #include "class_root.h"
24 #include "collector/garbage_collector.h"
25 #include "jni/java_vm_ext.h"
26 #include "mirror/class-inl.h"
27 #include "mirror/object-inl.h"
28 #include "mirror/reference-inl.h"
29 #include "nativehelper/scoped_local_ref.h"
30 #include "object_callbacks.h"
31 #include "reflection.h"
32 #include "scoped_thread_state_change-inl.h"
33 #include "task_processor.h"
34 #include "thread_pool.h"
35 #include "well_known_classes.h"
36
37 namespace art {
38 namespace gc {
39
40 static constexpr bool kAsyncReferenceQueueAdd = false;
41
ReferenceProcessor()42 ReferenceProcessor::ReferenceProcessor()
43 : collector_(nullptr),
44 preserving_references_(false),
45 condition_("reference processor condition", *Locks::reference_processor_lock_) ,
46 soft_reference_queue_(Locks::reference_queue_soft_references_lock_),
47 weak_reference_queue_(Locks::reference_queue_weak_references_lock_),
48 finalizer_reference_queue_(Locks::reference_queue_finalizer_references_lock_),
49 phantom_reference_queue_(Locks::reference_queue_phantom_references_lock_),
50 cleared_references_(Locks::reference_queue_cleared_references_lock_) {
51 }
52
GetSlowPathFlagOffset(ObjPtr<mirror::Class> reference_class)53 static inline MemberOffset GetSlowPathFlagOffset(ObjPtr<mirror::Class> reference_class)
54 REQUIRES_SHARED(Locks::mutator_lock_) {
55 DCHECK(reference_class == GetClassRoot<mirror::Reference>());
56 // Second static field
57 ArtField* field = reference_class->GetStaticField(1);
58 DCHECK_STREQ(field->GetName(), "slowPathEnabled");
59 return field->GetOffset();
60 }
61
SetSlowPathFlag(bool enabled)62 static inline void SetSlowPathFlag(bool enabled) REQUIRES_SHARED(Locks::mutator_lock_) {
63 ObjPtr<mirror::Class> reference_class = GetClassRoot<mirror::Reference>();
64 MemberOffset slow_path_offset = GetSlowPathFlagOffset(reference_class);
65 reference_class->SetFieldBoolean</* kTransactionActive= */ false, /* kCheckTransaction= */ false>(
66 slow_path_offset, enabled ? 1 : 0);
67 }
68
EnableSlowPath()69 void ReferenceProcessor::EnableSlowPath() {
70 SetSlowPathFlag(/* enabled= */ true);
71 }
72
DisableSlowPath(Thread * self)73 void ReferenceProcessor::DisableSlowPath(Thread* self) {
74 SetSlowPathFlag(/* enabled= */ false);
75 condition_.Broadcast(self);
76 }
77
SlowPathEnabled()78 bool ReferenceProcessor::SlowPathEnabled() {
79 ObjPtr<mirror::Class> reference_class = GetClassRoot<mirror::Reference>();
80 MemberOffset slow_path_offset = GetSlowPathFlagOffset(reference_class);
81 return reference_class->GetFieldBoolean(slow_path_offset);
82 }
83
BroadcastForSlowPath(Thread * self)84 void ReferenceProcessor::BroadcastForSlowPath(Thread* self) {
85 MutexLock mu(self, *Locks::reference_processor_lock_);
86 condition_.Broadcast(self);
87 }
88
GetReferent(Thread * self,ObjPtr<mirror::Reference> reference)89 ObjPtr<mirror::Object> ReferenceProcessor::GetReferent(Thread* self,
90 ObjPtr<mirror::Reference> reference) {
91 if (!kUseReadBarrier || self->GetWeakRefAccessEnabled()) {
92 // Under read barrier / concurrent copying collector, it's not safe to call GetReferent() when
93 // weak ref access is disabled as the call includes a read barrier which may push a ref onto the
94 // mark stack and interfere with termination of marking.
95 const ObjPtr<mirror::Object> referent = reference->GetReferent();
96 // If the referent is null then it is already cleared, we can just return null since there is no
97 // scenario where it becomes non-null during the reference processing phase.
98 if (UNLIKELY(!SlowPathEnabled()) || referent == nullptr) {
99 return referent;
100 }
101 }
102 MutexLock mu(self, *Locks::reference_processor_lock_);
103 while ((!kUseReadBarrier && SlowPathEnabled()) ||
104 (kUseReadBarrier && !self->GetWeakRefAccessEnabled())) {
105 ObjPtr<mirror::Object> referent = reference->GetReferent<kWithoutReadBarrier>();
106 // If the referent became cleared, return it. Don't need barrier since thread roots can't get
107 // updated until after we leave the function due to holding the mutator lock.
108 if (referent == nullptr) {
109 return nullptr;
110 }
111 // Try to see if the referent is already marked by using the is_marked_callback. We can return
112 // it to the mutator as long as the GC is not preserving references.
113 if (LIKELY(collector_ != nullptr)) {
114 // If it's null it means not marked, but it could become marked if the referent is reachable
115 // by finalizer referents. So we cannot return in this case and must block. Otherwise, we
116 // can return it to the mutator as long as the GC is not preserving references, in which
117 // case only black nodes can be safely returned. If the GC is preserving references, the
118 // mutator could take a white field from a grey or white node and move it somewhere else
119 // in the heap causing corruption since this field would get swept.
120 // Use the cached referent instead of calling GetReferent since other threads could call
121 // Reference.clear() after we did the null check resulting in a null pointer being
122 // incorrectly passed to IsMarked. b/33569625
123 ObjPtr<mirror::Object> forwarded_ref = collector_->IsMarked(referent.Ptr());
124 if (forwarded_ref != nullptr) {
125 // Non null means that it is marked.
126 if (!preserving_references_ ||
127 (LIKELY(!reference->IsFinalizerReferenceInstance()) && reference->IsUnprocessed())) {
128 return forwarded_ref;
129 }
130 }
131 }
132 // Check and run the empty checkpoint before blocking so the empty checkpoint will work in the
133 // presence of threads blocking for weak ref access.
134 self->CheckEmptyCheckpointFromWeakRefAccess(Locks::reference_processor_lock_);
135 condition_.WaitHoldingLocks(self);
136 }
137 return reference->GetReferent();
138 }
139
StartPreservingReferences(Thread * self)140 void ReferenceProcessor::StartPreservingReferences(Thread* self) {
141 MutexLock mu(self, *Locks::reference_processor_lock_);
142 preserving_references_ = true;
143 }
144
StopPreservingReferences(Thread * self)145 void ReferenceProcessor::StopPreservingReferences(Thread* self) {
146 MutexLock mu(self, *Locks::reference_processor_lock_);
147 preserving_references_ = false;
148 // We are done preserving references, some people who are blocked may see a marked referent.
149 condition_.Broadcast(self);
150 }
151
152 // Process reference class instances and schedule finalizations.
ProcessReferences(bool concurrent,TimingLogger * timings,bool clear_soft_references,collector::GarbageCollector * collector)153 void ReferenceProcessor::ProcessReferences(bool concurrent,
154 TimingLogger* timings,
155 bool clear_soft_references,
156 collector::GarbageCollector* collector) {
157 TimingLogger::ScopedTiming t(concurrent ? __FUNCTION__ : "(Paused)ProcessReferences", timings);
158 Thread* self = Thread::Current();
159 {
160 MutexLock mu(self, *Locks::reference_processor_lock_);
161 collector_ = collector;
162 if (!kUseReadBarrier) {
163 CHECK_EQ(SlowPathEnabled(), concurrent) << "Slow path must be enabled iff concurrent";
164 } else {
165 // Weak ref access is enabled at Zygote compaction by SemiSpace (concurrent == false).
166 CHECK_EQ(!self->GetWeakRefAccessEnabled(), concurrent);
167 }
168 }
169 if (kIsDebugBuild && collector->IsTransactionActive()) {
170 // In transaction mode, we shouldn't enqueue any Reference to the queues.
171 // See DelayReferenceReferent().
172 DCHECK(soft_reference_queue_.IsEmpty());
173 DCHECK(weak_reference_queue_.IsEmpty());
174 DCHECK(finalizer_reference_queue_.IsEmpty());
175 DCHECK(phantom_reference_queue_.IsEmpty());
176 }
177 // Unless required to clear soft references with white references, preserve some white referents.
178 if (!clear_soft_references) {
179 TimingLogger::ScopedTiming split(concurrent ? "ForwardSoftReferences" :
180 "(Paused)ForwardSoftReferences", timings);
181 if (concurrent) {
182 StartPreservingReferences(self);
183 }
184 // TODO: Add smarter logic for preserving soft references. The behavior should be a conditional
185 // mark if the SoftReference is supposed to be preserved.
186 soft_reference_queue_.ForwardSoftReferences(collector);
187 collector->ProcessMarkStack();
188 if (concurrent) {
189 StopPreservingReferences(self);
190 }
191 }
192 // Clear all remaining soft and weak references with white referents.
193 soft_reference_queue_.ClearWhiteReferences(&cleared_references_, collector);
194 weak_reference_queue_.ClearWhiteReferences(&cleared_references_, collector);
195 {
196 TimingLogger::ScopedTiming t2(concurrent ? "EnqueueFinalizerReferences" :
197 "(Paused)EnqueueFinalizerReferences", timings);
198 if (concurrent) {
199 StartPreservingReferences(self);
200 }
201 // Preserve all white objects with finalize methods and schedule them for finalization.
202 finalizer_reference_queue_.EnqueueFinalizerReferences(&cleared_references_, collector);
203 collector->ProcessMarkStack();
204 if (concurrent) {
205 StopPreservingReferences(self);
206 }
207 }
208 // Clear all finalizer referent reachable soft and weak references with white referents.
209 soft_reference_queue_.ClearWhiteReferences(&cleared_references_, collector);
210 weak_reference_queue_.ClearWhiteReferences(&cleared_references_, collector);
211 // Clear all phantom references with white referents.
212 phantom_reference_queue_.ClearWhiteReferences(&cleared_references_, collector);
213 // At this point all reference queues other than the cleared references should be empty.
214 DCHECK(soft_reference_queue_.IsEmpty());
215 DCHECK(weak_reference_queue_.IsEmpty());
216 DCHECK(finalizer_reference_queue_.IsEmpty());
217 DCHECK(phantom_reference_queue_.IsEmpty());
218 {
219 MutexLock mu(self, *Locks::reference_processor_lock_);
220 // Need to always do this since the next GC may be concurrent. Doing this for only concurrent
221 // could result in a stale is_marked_callback_ being called before the reference processing
222 // starts since there is a small window of time where slow_path_enabled_ is enabled but the
223 // callback isn't yet set.
224 collector_ = nullptr;
225 if (!kUseReadBarrier && concurrent) {
226 // Done processing, disable the slow path and broadcast to the waiters.
227 DisableSlowPath(self);
228 }
229 }
230 }
231
232 // Process the "referent" field in a java.lang.ref.Reference. If the referent has not yet been
233 // marked, put it on the appropriate list in the heap for later processing.
DelayReferenceReferent(ObjPtr<mirror::Class> klass,ObjPtr<mirror::Reference> ref,collector::GarbageCollector * collector)234 void ReferenceProcessor::DelayReferenceReferent(ObjPtr<mirror::Class> klass,
235 ObjPtr<mirror::Reference> ref,
236 collector::GarbageCollector* collector) {
237 // klass can be the class of the old object if the visitor already updated the class of ref.
238 DCHECK(klass != nullptr);
239 DCHECK(klass->IsTypeOfReferenceClass());
240 mirror::HeapReference<mirror::Object>* referent = ref->GetReferentReferenceAddr();
241 // do_atomic_update needs to be true because this happens outside of the reference processing
242 // phase.
243 if (!collector->IsNullOrMarkedHeapReference(referent, /*do_atomic_update=*/true)) {
244 if (UNLIKELY(collector->IsTransactionActive())) {
245 // In transaction mode, keep the referent alive and avoid any reference processing to avoid the
246 // issue of rolling back reference processing. do_atomic_update needs to be true because this
247 // happens outside of the reference processing phase.
248 if (!referent->IsNull()) {
249 collector->MarkHeapReference(referent, /*do_atomic_update=*/ true);
250 }
251 return;
252 }
253 Thread* self = Thread::Current();
254 // TODO: Remove these locks, and use atomic stacks for storing references?
255 // We need to check that the references haven't already been enqueued since we can end up
256 // scanning the same reference multiple times due to dirty cards.
257 if (klass->IsSoftReferenceClass()) {
258 soft_reference_queue_.AtomicEnqueueIfNotEnqueued(self, ref);
259 } else if (klass->IsWeakReferenceClass()) {
260 weak_reference_queue_.AtomicEnqueueIfNotEnqueued(self, ref);
261 } else if (klass->IsFinalizerReferenceClass()) {
262 finalizer_reference_queue_.AtomicEnqueueIfNotEnqueued(self, ref);
263 } else if (klass->IsPhantomReferenceClass()) {
264 phantom_reference_queue_.AtomicEnqueueIfNotEnqueued(self, ref);
265 } else {
266 LOG(FATAL) << "Invalid reference type " << klass->PrettyClass() << " " << std::hex
267 << klass->GetAccessFlags();
268 }
269 }
270 }
271
UpdateRoots(IsMarkedVisitor * visitor)272 void ReferenceProcessor::UpdateRoots(IsMarkedVisitor* visitor) {
273 cleared_references_.UpdateRoots(visitor);
274 }
275
276 class ClearedReferenceTask : public HeapTask {
277 public:
ClearedReferenceTask(jobject cleared_references)278 explicit ClearedReferenceTask(jobject cleared_references)
279 : HeapTask(NanoTime()), cleared_references_(cleared_references) {
280 }
Run(Thread * thread)281 void Run(Thread* thread) override {
282 ScopedObjectAccess soa(thread);
283 jvalue args[1];
284 args[0].l = cleared_references_;
285 InvokeWithJValues(soa, nullptr, WellKnownClasses::java_lang_ref_ReferenceQueue_add, args);
286 soa.Env()->DeleteGlobalRef(cleared_references_);
287 }
288
289 private:
290 const jobject cleared_references_;
291 };
292
CollectClearedReferences(Thread * self)293 SelfDeletingTask* ReferenceProcessor::CollectClearedReferences(Thread* self) {
294 Locks::mutator_lock_->AssertNotHeld(self);
295 // By default we don't actually need to do anything. Just return this no-op task to avoid having
296 // to put in ifs.
297 std::unique_ptr<SelfDeletingTask> result(new FunctionTask([](Thread*) {}));
298 // When a runtime isn't started there are no reference queues to care about so ignore.
299 if (!cleared_references_.IsEmpty()) {
300 if (LIKELY(Runtime::Current()->IsStarted())) {
301 jobject cleared_references;
302 {
303 ReaderMutexLock mu(self, *Locks::mutator_lock_);
304 cleared_references = self->GetJniEnv()->GetVm()->AddGlobalRef(
305 self, cleared_references_.GetList());
306 }
307 if (kAsyncReferenceQueueAdd) {
308 // TODO: This can cause RunFinalization to terminate before newly freed objects are
309 // finalized since they may not be enqueued by the time RunFinalization starts.
310 Runtime::Current()->GetHeap()->GetTaskProcessor()->AddTask(
311 self, new ClearedReferenceTask(cleared_references));
312 } else {
313 result.reset(new ClearedReferenceTask(cleared_references));
314 }
315 }
316 cleared_references_.Clear();
317 }
318 return result.release();
319 }
320
ClearReferent(ObjPtr<mirror::Reference> ref)321 void ReferenceProcessor::ClearReferent(ObjPtr<mirror::Reference> ref) {
322 Thread* self = Thread::Current();
323 MutexLock mu(self, *Locks::reference_processor_lock_);
324 // Need to wait until reference processing is done since IsMarkedHeapReference does not have a
325 // CAS. If we do not wait, it can result in the GC un-clearing references due to race conditions.
326 // This also handles the race where the referent gets cleared after a null check but before
327 // IsMarkedHeapReference is called.
328 WaitUntilDoneProcessingReferences(self);
329 if (Runtime::Current()->IsActiveTransaction()) {
330 ref->ClearReferent<true>();
331 } else {
332 ref->ClearReferent<false>();
333 }
334 }
335
WaitUntilDoneProcessingReferences(Thread * self)336 void ReferenceProcessor::WaitUntilDoneProcessingReferences(Thread* self) {
337 // Wait until we are done processing reference.
338 while ((!kUseReadBarrier && SlowPathEnabled()) ||
339 (kUseReadBarrier && !self->GetWeakRefAccessEnabled())) {
340 // Check and run the empty checkpoint before blocking so the empty checkpoint will work in the
341 // presence of threads blocking for weak ref access.
342 self->CheckEmptyCheckpointFromWeakRefAccess(Locks::reference_processor_lock_);
343 condition_.WaitHoldingLocks(self);
344 }
345 }
346
MakeCircularListIfUnenqueued(ObjPtr<mirror::FinalizerReference> reference)347 bool ReferenceProcessor::MakeCircularListIfUnenqueued(
348 ObjPtr<mirror::FinalizerReference> reference) {
349 Thread* self = Thread::Current();
350 MutexLock mu(self, *Locks::reference_processor_lock_);
351 WaitUntilDoneProcessingReferences(self);
352 // At this point, since the sentinel of the reference is live, it is guaranteed to not be
353 // enqueued if we just finished processing references. Otherwise, we may be doing the main GC
354 // phase. Since we are holding the reference processor lock, it guarantees that reference
355 // processing can't begin. The GC could have just enqueued the reference one one of the internal
356 // GC queues, but since we hold the lock finalizer_reference_queue_ lock it also prevents this
357 // race.
358 MutexLock mu2(self, *Locks::reference_queue_finalizer_references_lock_);
359 if (reference->IsUnprocessed()) {
360 CHECK(reference->IsFinalizerReferenceInstance());
361 reference->SetPendingNext(reference);
362 return true;
363 }
364 return false;
365 }
366
367 } // namespace gc
368 } // namespace art
369