139e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier/* 239e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * Copyright (C) 2013 The Android Open Source Project 339e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * 439e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * Licensed under the Apache License, Version 2.0 (the "License"); 539e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * you may not use this file except in compliance with the License. 639e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * You may obtain a copy of the License at 739e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * 839e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * http://www.apache.org/licenses/LICENSE-2.0 939e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * 1039e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * Unless required by applicable law or agreed to in writing, software 1139e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * distributed under the License is distributed on an "AS IS" BASIS, 1239e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1339e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * See the License for the specific language governing permissions and 1439e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier * limitations under the License. 1539e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier */ 1639e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 1739e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier#include "reference_queue.h" 1839e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 1939e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier#include "accounting/card_table-inl.h" 202cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi#include "collector/concurrent_copying.h" 2139e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier#include "heap.h" 2239e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier#include "mirror/class-inl.h" 2339e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier#include "mirror/object-inl.h" 248fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartier#include "mirror/reference-inl.h" 2539e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 2639e3261168e7761fea6d873494d7c5d191285791Mathieu Chartiernamespace art { 2739e3261168e7761fea6d873494d7c5d191285791Mathieu Chartiernamespace gc { 2839e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 29a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu ChartierReferenceQueue::ReferenceQueue(Mutex* lock) : lock_(lock), list_(nullptr) { 3039e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier} 3139e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 328fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartiervoid ReferenceQueue::AtomicEnqueueIfNotEnqueued(Thread* self, mirror::Reference* ref) { 332cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier DCHECK(ref != nullptr); 34a5a53efea976af505f4f849b5925d5e14c4f8e5cMathieu Chartier MutexLock mu(self, *lock_); 35c4695dfdab80c280c98a89c20e027a3804191585Richard Uhler if (ref->IsUnprocessed()) { 36c4695dfdab80c280c98a89c20e027a3804191585Richard Uhler EnqueueReference(ref); 3739e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } 3839e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier} 3939e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 408fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartiervoid ReferenceQueue::EnqueueReference(mirror::Reference* ref) { 412cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier DCHECK(ref != nullptr); 42c4695dfdab80c280c98a89c20e027a3804191585Richard Uhler CHECK(ref->IsUnprocessed()); 4339e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier if (IsEmpty()) { 4439e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier // 1 element cyclic queue, ie: Reference ref = ..; ref.pendingNext = ref; 4539e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier list_ = ref; 4639e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } else { 478fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartier mirror::Reference* head = list_->GetPendingNext(); 48c4695dfdab80c280c98a89c20e027a3804191585Richard Uhler DCHECK(head != nullptr); 49522d51b088c63d757e487d07d769f8f09e042f2aRichard Uhler ref->SetPendingNext(head); 508fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartier } 51c4695dfdab80c280c98a89c20e027a3804191585Richard Uhler // Add the reference in the middle to preserve the cycle. 52522d51b088c63d757e487d07d769f8f09e042f2aRichard Uhler list_->SetPendingNext(ref); 5339e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier} 5439e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 558fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartiermirror::Reference* ReferenceQueue::DequeuePendingReference() { 5639e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier DCHECK(!IsEmpty()); 57c4695dfdab80c280c98a89c20e027a3804191585Richard Uhler mirror::Reference* ref = list_->GetPendingNext(); 58c4695dfdab80c280c98a89c20e027a3804191585Richard Uhler DCHECK(ref != nullptr); 5939e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier // Note: the following code is thread-safe because it is only called from ProcessReferences which 6039e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier // is single threaded. 61c4695dfdab80c280c98a89c20e027a3804191585Richard Uhler if (list_ == ref) { 6239e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier list_ = nullptr; 6339e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } else { 64c4695dfdab80c280c98a89c20e027a3804191585Richard Uhler mirror::Reference* next = ref->GetPendingNext(); 65522d51b088c63d757e487d07d769f8f09e042f2aRichard Uhler list_->SetPendingNext(next); 6639e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } 67522d51b088c63d757e487d07d769f8f09e042f2aRichard Uhler ref->SetPendingNext(nullptr); 682cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi Heap* heap = Runtime::Current()->GetHeap(); 692cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi if (kUseBakerOrBrooksReadBarrier && heap->CurrentCollectorType() == kCollectorTypeCC && 702cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi heap->ConcurrentCopyingCollector()->IsActive()) { 7170c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi // Change the gray ptr we left in ConcurrentCopying::ProcessMarkStackRef() to black or white. 7270c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi // We check IsActive() above because we don't want to do this when the zygote compaction 7370c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi // collector (SemiSpace) is running. 742cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi CHECK(ref != nullptr); 7570c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi collector::ConcurrentCopying* concurrent_copying = heap->ConcurrentCopyingCollector(); 7670c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi const bool is_moving = concurrent_copying->RegionSpace()->IsInToSpace(ref); 7770c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi if (ref->GetReadBarrierPointer() == ReadBarrier::GrayPtr()) { 7870c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi if (is_moving) { 7970c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi ref->AtomicSetReadBarrierPointer(ReadBarrier::GrayPtr(), ReadBarrier::WhitePtr()); 8070c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi CHECK_EQ(ref->GetReadBarrierPointer(), ReadBarrier::WhitePtr()); 8170c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi } else { 8270c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi ref->AtomicSetReadBarrierPointer(ReadBarrier::GrayPtr(), ReadBarrier::BlackPtr()); 8370c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi CHECK_EQ(ref->GetReadBarrierPointer(), ReadBarrier::BlackPtr()); 8470c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi } 852cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi } else { 8670c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi // In ConcurrentCopying::ProcessMarkStackRef() we may leave a black or white Reference in the 8770c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi // queue and find it here, which is OK. Check that the color makes sense depending on whether 8870c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi // the Reference is moving or not and that the referent has been marked. 8970c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi if (is_moving) { 9070c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi CHECK_EQ(ref->GetReadBarrierPointer(), ReadBarrier::WhitePtr()) 9170c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi << "ref=" << ref << " rb_ptr=" << ref->GetReadBarrierPointer(); 9270c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi } else { 9370c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi CHECK_EQ(ref->GetReadBarrierPointer(), ReadBarrier::BlackPtr()) 9470c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi << "ref=" << ref << " rb_ptr=" << ref->GetReadBarrierPointer(); 9570c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi } 9670c08d3c913ce2150cd620ea87b919f8eb5bd953Hiroshi Yamauchi mirror::Object* referent = ref->GetReferent<kWithoutReadBarrier>(); 97d2bb5ba17c5760aee5347de3c32b4f2f47a33d54Hiroshi Yamauchi // The referent could be null if it's cleared by a mutator (Reference.clear()). 98d2bb5ba17c5760aee5347de3c32b4f2f47a33d54Hiroshi Yamauchi if (referent != nullptr) { 99d2bb5ba17c5760aee5347de3c32b4f2f47a33d54Hiroshi Yamauchi CHECK(concurrent_copying->IsInToSpace(referent)) 100d2bb5ba17c5760aee5347de3c32b4f2f47a33d54Hiroshi Yamauchi << "ref=" << ref << " rb_ptr=" << ref->GetReadBarrierPointer() 101d2bb5ba17c5760aee5347de3c32b4f2f47a33d54Hiroshi Yamauchi << " referent=" << referent; 102d2bb5ba17c5760aee5347de3c32b4f2f47a33d54Hiroshi Yamauchi } 1032cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi } 1042cd334ae2d4287216523882f0d298cf3901b7ab1Hiroshi Yamauchi } 10539e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier return ref; 10639e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier} 10739e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 10839e3261168e7761fea6d873494d7c5d191285791Mathieu Chartiervoid ReferenceQueue::Dump(std::ostream& os) const { 1098fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartier mirror::Reference* cur = list_; 11039e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier os << "Reference starting at list_=" << list_ << "\n"; 1119e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier if (cur == nullptr) { 1129e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier return; 1139e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier } 1149e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier do { 1158fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartier mirror::Reference* pending_next = cur->GetPendingNext(); 1169e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier os << "Reference= " << cur << " PendingNext=" << pending_next; 1178fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartier if (cur->IsFinalizerReferenceInstance()) { 1188fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartier os << " Zombie=" << cur->AsFinalizerReference()->GetZombie(); 11939e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } 12039e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier os << "\n"; 12139e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier cur = pending_next; 1229e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier } while (cur != list_); 1239e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier} 1249e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier 1259e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartiersize_t ReferenceQueue::GetLength() const { 1269e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier size_t count = 0; 1279e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier mirror::Reference* cur = list_; 1289e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier if (cur != nullptr) { 1299e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier do { 1309e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier ++count; 1319e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier cur = cur->GetPendingNext(); 1329e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier } while (cur != list_); 13339e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } 1349e2094f921b63582e84d65849b1c5c6dc4d22b44Mathieu Chartier return count; 13539e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier} 13639e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 137308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartiervoid ReferenceQueue::ClearWhiteReferences(ReferenceQueue* cleared_references, 13897509954404d031594b2ecbda607314d169d512eMathieu Chartier collector::GarbageCollector* collector) { 13939e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier while (!IsEmpty()) { 1408fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartier mirror::Reference* ref = DequeuePendingReference(); 141308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier mirror::HeapReference<mirror::Object>* referent_addr = ref->GetReferentReferenceAddr(); 14297509954404d031594b2ecbda607314d169d512eMathieu Chartier if (referent_addr->AsMirrorPtr() != nullptr && 14397509954404d031594b2ecbda607314d169d512eMathieu Chartier !collector->IsMarkedHeapReference(referent_addr)) { 144308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier // Referent is white, clear it. 145308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier if (Runtime::Current()->IsActiveTransaction()) { 146308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier ref->ClearReferent<true>(); 147308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier } else { 148308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier ref->ClearReferent<false>(); 149308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier } 150c4695dfdab80c280c98a89c20e027a3804191585Richard Uhler cleared_references->EnqueueReference(ref); 15139e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } 15239e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } 15339e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier} 15439e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 155308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartiervoid ReferenceQueue::EnqueueFinalizerReferences(ReferenceQueue* cleared_references, 15697509954404d031594b2ecbda607314d169d512eMathieu Chartier collector::GarbageCollector* collector) { 15739e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier while (!IsEmpty()) { 1588fa2dad7fe7909c8335101d6c8904ae997cdf29fMathieu Chartier mirror::FinalizerReference* ref = DequeuePendingReference()->AsFinalizerReference(); 159308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier mirror::HeapReference<mirror::Object>* referent_addr = ref->GetReferentReferenceAddr(); 16097509954404d031594b2ecbda607314d169d512eMathieu Chartier if (referent_addr->AsMirrorPtr() != nullptr && 16197509954404d031594b2ecbda607314d169d512eMathieu Chartier !collector->IsMarkedHeapReference(referent_addr)) { 16297509954404d031594b2ecbda607314d169d512eMathieu Chartier mirror::Object* forward_address = collector->MarkObject(referent_addr->AsMirrorPtr()); 163308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier // Move the updated referent to the zombie field. 164308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier if (Runtime::Current()->IsActiveTransaction()) { 165308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier ref->SetZombie<true>(forward_address); 166308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier ref->ClearReferent<true>(); 167308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier } else { 168308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier ref->SetZombie<false>(forward_address); 169308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier ref->ClearReferent<false>(); 17039e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } 171308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier cleared_references->EnqueueReference(ref); 17239e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } 17339e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } 17439e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier} 17539e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 17697509954404d031594b2ecbda607314d169d512eMathieu Chartiervoid ReferenceQueue::ForwardSoftReferences(MarkObjectVisitor* visitor) { 177530e1b54887b6b5e7d648170096e22a5f1850ea8Fred Shih if (UNLIKELY(IsEmpty())) { 178530e1b54887b6b5e7d648170096e22a5f1850ea8Fred Shih return; 179530e1b54887b6b5e7d648170096e22a5f1850ea8Fred Shih } 180530e1b54887b6b5e7d648170096e22a5f1850ea8Fred Shih mirror::Reference* const head = list_; 181530e1b54887b6b5e7d648170096e22a5f1850ea8Fred Shih mirror::Reference* ref = head; 182530e1b54887b6b5e7d648170096e22a5f1850ea8Fred Shih do { 183308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier mirror::HeapReference<mirror::Object>* referent_addr = ref->GetReferentReferenceAddr(); 184308351ada0008b0cbe1a5afc31c302c975554ee4Mathieu Chartier if (referent_addr->AsMirrorPtr() != nullptr) { 18597509954404d031594b2ecbda607314d169d512eMathieu Chartier visitor->MarkHeapReference(referent_addr); 18639e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier } 187530e1b54887b6b5e7d648170096e22a5f1850ea8Fred Shih ref = ref->GetPendingNext(); 188530e1b54887b6b5e7d648170096e22a5f1850ea8Fred Shih } while (LIKELY(ref != head)); 18939e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier} 19039e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier 19197509954404d031594b2ecbda607314d169d512eMathieu Chartiervoid ReferenceQueue::UpdateRoots(IsMarkedVisitor* visitor) { 19252e4b43d62896b56f8c2bd041e528472bb4a0d8dMathieu Chartier if (list_ != nullptr) { 19397509954404d031594b2ecbda607314d169d512eMathieu Chartier list_ = down_cast<mirror::Reference*>(visitor->IsMarked(list_)); 19452e4b43d62896b56f8c2bd041e528472bb4a0d8dMathieu Chartier } 19552e4b43d62896b56f8c2bd041e528472bb4a0d8dMathieu Chartier} 19652e4b43d62896b56f8c2bd041e528472bb4a0d8dMathieu Chartier 19739e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier} // namespace gc 19839e3261168e7761fea6d873494d7c5d191285791Mathieu Chartier} // namespace art 199