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