/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mod_union_table.h"

#include <memory>

#include "base/logging.h"  // For VLOG
#include "base/stl_util.h"
#include "bitmap-inl.h"
#include "card_table-inl.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/heap.h"
#include "gc/space/image_space.h"
#include "gc/space/space.h"
#include "mirror/object-inl.h"
#include "mirror/object-refvisitor-inl.h"
#include "object_callbacks.h"
#include "space_bitmap-inl.h"
#include "thread-current-inl.h"

namespace art {
namespace gc {
namespace accounting {

class ModUnionAddToCardSetVisitor {
 public:
  explicit ModUnionAddToCardSetVisitor(ModUnionTable::CardSet* const cleared_cards)
      : cleared_cards_(cleared_cards) {}

  inline void operator()(uint8_t* card,
                         uint8_t expected_value,
                         [[maybe_unused]] uint8_t new_value) const {
    if (expected_value == CardTable::kCardDirty) {
      cleared_cards_->insert(card);
    }
  }

 private:
  ModUnionTable::CardSet* const cleared_cards_;
};

class ModUnionAddToCardBitmapVisitor {
 public:
  ModUnionAddToCardBitmapVisitor(ModUnionTable::CardBitmap* bitmap, CardTable* card_table)
      : bitmap_(bitmap), card_table_(card_table) {}

  inline void operator()(uint8_t* card,
                         uint8_t expected_value,
                         [[maybe_unused]] uint8_t new_value) const {
    if (expected_value == CardTable::kCardDirty) {
      // We want the address the card represents, not the address of the card.
      bitmap_->Set(reinterpret_cast<uintptr_t>(card_table_->AddrFromCard(card)));
    }
  }

 private:
  ModUnionTable::CardBitmap* const bitmap_;
  CardTable* const card_table_;
};

class ModUnionAddToCardVectorVisitor {
 public:
  explicit ModUnionAddToCardVectorVisitor(std::vector<uint8_t*>* cleared_cards)
      : cleared_cards_(cleared_cards) {
  }

  void operator()(uint8_t* card, uint8_t expected_card, [[maybe_unused]] uint8_t new_card) const {
    if (expected_card == CardTable::kCardDirty) {
      cleared_cards_->push_back(card);
    }
  }

 private:
  std::vector<uint8_t*>* const cleared_cards_;
};

class ModUnionUpdateObjectReferencesVisitor {
 public:
  ModUnionUpdateObjectReferencesVisitor(MarkObjectVisitor* visitor,
                                        space::ContinuousSpace* from_space,
                                        space::ContinuousSpace* immune_space,
                                        bool* contains_reference_to_other_space)
    : visitor_(visitor),
      from_space_(from_space),
      immune_space_(immune_space),
      contains_reference_to_other_space_(contains_reference_to_other_space) {}

  // Extra parameters are required since we use this same visitor signature for checking objects.
  void operator()(mirror::Object* obj, MemberOffset offset, [[maybe_unused]] bool is_static) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    MarkReference(obj->GetFieldObjectReferenceAddr(offset));
  }

  void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    VisitRoot(root);
  }

  void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    MarkReference(root);
  }

 private:
  template<typename CompressedReferenceType>
  void MarkReference(CompressedReferenceType* obj_ptr) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    // Only add the reference if it is non null and fits our criteria.
    mirror::Object* ref = obj_ptr->AsMirrorPtr();
    if (ref != nullptr && !from_space_->HasAddress(ref) && !immune_space_->HasAddress(ref)) {
      *contains_reference_to_other_space_ = true;
      mirror::Object* new_object = visitor_->MarkObject(ref);
      if (ref != new_object) {
        obj_ptr->Assign(new_object);
      }
    }
  }

  MarkObjectVisitor* const visitor_;
  // Space which we are scanning
  space::ContinuousSpace* const from_space_;
  space::ContinuousSpace* const immune_space_;
  // Set if we have any references to another space.
  bool* const contains_reference_to_other_space_;
};

class ModUnionScanImageRootVisitor {
 public:
  // Immune space is any other space which we don't care about references to. Currently this is
  // the image space in the case of the zygote mod union table.
  ModUnionScanImageRootVisitor(MarkObjectVisitor* visitor,
                               space::ContinuousSpace* from_space,
                               space::ContinuousSpace* immune_space,
                               bool* contains_reference_to_other_space)
      : visitor_(visitor),
        from_space_(from_space),
        immune_space_(immune_space),
        contains_reference_to_other_space_(contains_reference_to_other_space) {}

  void operator()(mirror::Object* root) const
      REQUIRES(Locks::heap_bitmap_lock_)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    DCHECK(root != nullptr);
    ModUnionUpdateObjectReferencesVisitor ref_visitor(visitor_,
                                                      from_space_,
                                                      immune_space_,
                                                      contains_reference_to_other_space_);
    root->VisitReferences(ref_visitor, VoidFunctor());
  }

 private:
  MarkObjectVisitor* const visitor_;
  // Space which we are scanning
  space::ContinuousSpace* const from_space_;
  space::ContinuousSpace* const immune_space_;
  // Set if we have any references to another space.
  bool* const contains_reference_to_other_space_;
};

void ModUnionTableReferenceCache::ProcessCards() {
  CardTable* card_table = GetHeap()->GetCardTable();
  ModUnionAddToCardSetVisitor visitor(&cleared_cards_);
  // Clear dirty cards in the this space and update the corresponding mod-union bits.
  card_table->ModifyCardsAtomic(space_->Begin(), space_->End(), AgeCardVisitor(), visitor);
}

void ModUnionTableReferenceCache::ClearTable() {
  cleared_cards_.clear();
  references_.clear();
}

class AddToReferenceArrayVisitor {
 public:
  AddToReferenceArrayVisitor(ModUnionTableReferenceCache* mod_union_table,
                             MarkObjectVisitor* visitor,
                             std::vector<mirror::HeapReference<mirror::Object>*>* references,
                             bool* has_target_reference)
      : mod_union_table_(mod_union_table),
        visitor_(visitor),
        references_(references),
        has_target_reference_(has_target_reference) {}

  // Extra parameters are required since we use this same visitor signature for checking objects.
  void operator()(mirror::Object* obj, MemberOffset offset, [[maybe_unused]] bool is_static) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    mirror::HeapReference<mirror::Object>* ref_ptr = obj->GetFieldObjectReferenceAddr(offset);
    mirror::Object* ref = ref_ptr->AsMirrorPtr();
    // Only add the reference if it is non null and fits our criteria.
    if (ref != nullptr && mod_union_table_->ShouldAddReference(ref)) {
      // Push the adddress of the reference.
      references_->push_back(ref_ptr);
    }
  }

  void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    if (!root->IsNull()) {
      VisitRoot(root);
    }
  }

  void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    if (mod_union_table_->ShouldAddReference(root->AsMirrorPtr())) {
      *has_target_reference_ = true;
      // TODO: Add MarkCompressedReference callback here.
      mirror::Object* old_ref = root->AsMirrorPtr();
      mirror::Object* new_ref = visitor_->MarkObject(old_ref);
      if (old_ref != new_ref) {
        root->Assign(new_ref);
      }
    }
  }

 private:
  ModUnionTableReferenceCache* const mod_union_table_;
  MarkObjectVisitor* const visitor_;
  std::vector<mirror::HeapReference<mirror::Object>*>* const references_;
  bool* const has_target_reference_;
};

class ModUnionReferenceVisitor {
 public:
  ModUnionReferenceVisitor(ModUnionTableReferenceCache* const mod_union_table,
                           MarkObjectVisitor* visitor,
                           std::vector<mirror::HeapReference<mirror::Object>*>* references,
                           bool* has_target_reference)
      : mod_union_table_(mod_union_table),
        visitor_(visitor),
        references_(references),
        has_target_reference_(has_target_reference) {}

  void operator()(mirror::Object* obj) const
      REQUIRES_SHARED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
    // We don't have an early exit since we use the visitor pattern, an early
    // exit should significantly speed this up.
    AddToReferenceArrayVisitor visitor(mod_union_table_,
                                       visitor_,
                                       references_,
                                       has_target_reference_);
    obj->VisitReferences(visitor, VoidFunctor());
  }

 private:
  ModUnionTableReferenceCache* const mod_union_table_;
  MarkObjectVisitor* const visitor_;
  std::vector<mirror::HeapReference<mirror::Object>*>* const references_;
  bool* const has_target_reference_;
};

class CheckReferenceVisitor {
 public:
  CheckReferenceVisitor(ModUnionTableReferenceCache* mod_union_table,
                        const std::set<mirror::Object*>& references)
      : mod_union_table_(mod_union_table),
        references_(references) {}

  // Extra parameters are required since we use this same visitor signature for checking objects.
  void operator()(mirror::Object* obj, MemberOffset offset, [[maybe_unused]] bool is_static) const
      REQUIRES_SHARED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
    mirror::Object* ref = obj->GetFieldObject<mirror::Object>(offset);
    if (ref != nullptr &&
        mod_union_table_->ShouldAddReference(ref) &&
        references_.find(ref) == references_.end()) {
      Heap* heap = mod_union_table_->GetHeap();
      space::ContinuousSpace* from_space = heap->FindContinuousSpaceFromObject(obj, false);
      space::ContinuousSpace* to_space = heap->FindContinuousSpaceFromObject(ref, false);
      LOG(INFO) << "Object " << reinterpret_cast<const void*>(obj) << "(" << obj->PrettyTypeOf()
                << ")" << "References "
                << reinterpret_cast<const void*>(ref) << "(" << mirror::Object::PrettyTypeOf(ref)
          << ") without being in mod-union table";
      LOG(INFO) << "FromSpace " << from_space->GetName() << " type "
          << from_space->GetGcRetentionPolicy();
      LOG(INFO) << "ToSpace " << to_space->GetName() << " type "
          << to_space->GetGcRetentionPolicy();
      heap->DumpSpaces(LOG_STREAM(INFO));
      LOG(FATAL) << "FATAL ERROR";
    }
  }

  void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    if (kIsDebugBuild && !root->IsNull()) {
      VisitRoot(root);
    }
  }

  void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    DCHECK(!mod_union_table_->ShouldAddReference(root->AsMirrorPtr()));
  }

 private:
  ModUnionTableReferenceCache* const mod_union_table_;
  const std::set<mirror::Object*>& references_;
};

class ModUnionCheckReferences {
 public:
  ModUnionCheckReferences(ModUnionTableReferenceCache* mod_union_table,
                          const std::set<mirror::Object*>& references)
      REQUIRES(Locks::heap_bitmap_lock_)
      : mod_union_table_(mod_union_table), references_(references) {}

  void operator()(mirror::Object* obj) const NO_THREAD_SAFETY_ANALYSIS {
    Locks::heap_bitmap_lock_->AssertSharedHeld(Thread::Current());
    CheckReferenceVisitor visitor(mod_union_table_, references_);
    obj->VisitReferences(visitor, VoidFunctor());
  }

 private:
  ModUnionTableReferenceCache* const mod_union_table_;
  const std::set<mirror::Object*>& references_;
};

class EmptyMarkObjectVisitor : public MarkObjectVisitor {
 public:
  mirror::Object* MarkObject(mirror::Object* obj) override {return obj;}
  void MarkHeapReference(mirror::HeapReference<mirror::Object>*, bool) override {}
};

void ModUnionTable::FilterCards() {
  EmptyMarkObjectVisitor visitor;
  // Use empty visitor since filtering is automatically done by UpdateAndMarkReferences.
  UpdateAndMarkReferences(&visitor);
}

void ModUnionTableReferenceCache::Verify() {
  // Start by checking that everything in the mod union table is marked.
  for (const auto& ref_pair : references_) {
    for (mirror::HeapReference<mirror::Object>* ref : ref_pair.second) {
      CHECK(heap_->IsLiveObjectLocked(ref->AsMirrorPtr()));
    }
  }

  // Check the references of each clean card which is also in the mod union table.
  CardTable* card_table = heap_->GetCardTable();
  ContinuousSpaceBitmap* live_bitmap = space_->GetLiveBitmap();
  for (const auto& ref_pair : references_) {
    const uint8_t* card = ref_pair.first;
    if (*card == CardTable::kCardClean) {
      std::set<mirror::Object*> reference_set;
      for (mirror::HeapReference<mirror::Object>* obj_ptr : ref_pair.second) {
        reference_set.insert(obj_ptr->AsMirrorPtr());
      }
      ModUnionCheckReferences visitor(this, reference_set);
      uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card));
      live_bitmap->VisitMarkedRange(start, start + CardTable::kCardSize, visitor);
    }
  }
}

void ModUnionTableReferenceCache::Dump(std::ostream& os) {
  CardTable* card_table = heap_->GetCardTable();
  os << "ModUnionTable cleared cards: [";
  for (uint8_t* card_addr : cleared_cards_) {
    uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card_addr));
    uintptr_t end = start + CardTable::kCardSize;
    os << reinterpret_cast<void*>(start) << "-" << reinterpret_cast<void*>(end) << ",";
  }
  os << "]\nModUnionTable references: [";
  for (const auto& ref_pair : references_) {
    const uint8_t* card_addr = ref_pair.first;
    uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card_addr));
    uintptr_t end = start + CardTable::kCardSize;
    os << reinterpret_cast<void*>(start) << "-" << reinterpret_cast<void*>(end) << "->{";
    for (mirror::HeapReference<mirror::Object>* ref : ref_pair.second) {
      os << reinterpret_cast<const void*>(ref->AsMirrorPtr()) << ",";
    }
    os << "},";
  }
}

void ModUnionTableReferenceCache::VisitObjects(ObjectCallback callback, void* arg) {
  CardTable* const card_table = heap_->GetCardTable();
  ContinuousSpaceBitmap* live_bitmap = space_->GetLiveBitmap();
  // Use an unordered_set for constant time search of card in the second loop.
  // We don't want to change cleared_cards_ to unordered so that traversals are
  // sequential in address order.
  // TODO: Optimize this.
  std::unordered_set<const uint8_t*> card_lookup_map;
  for (uint8_t* card : cleared_cards_) {
    uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card));
    uintptr_t end = start + CardTable::kCardSize;
    live_bitmap->VisitMarkedRange(start,
                                  end,
                                  [callback, arg](mirror::Object* obj) {
      callback(obj, arg);
    });
    card_lookup_map.insert(card);
  }
  for (const auto& pair : references_) {
    const uint8_t* card = pair.first;
    if (card_lookup_map.find(card) != card_lookup_map.end()) {
      continue;
    }
    uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card));
    uintptr_t end = start + CardTable::kCardSize;
    live_bitmap->VisitMarkedRange(start,
                                  end,
                                  [callback, arg](mirror::Object* obj) {
      callback(obj, arg);
    });
  }
}

void ModUnionTableReferenceCache::UpdateAndMarkReferences(MarkObjectVisitor* visitor) {
  CardTable* const card_table = heap_->GetCardTable();
  std::vector<mirror::HeapReference<mirror::Object>*> cards_references;
  // If has_target_reference is true then there was a GcRoot compressed reference which wasn't
  // added. In this case we need to keep the card dirty.
  // We don't know if the GcRoot addresses will remain constant, for example, classloaders have a
  // hash set of GcRoot which may be resized or modified.
  bool has_target_reference;
  ModUnionReferenceVisitor add_visitor(this, visitor, &cards_references, &has_target_reference);
  CardSet new_cleared_cards;
  for (uint8_t* card : cleared_cards_) {
    // Clear and re-compute alloc space references associated with this card.
    cards_references.clear();
    has_target_reference = false;
    uintptr_t start = reinterpret_cast<uintptr_t>(card_table->AddrFromCard(card));
    uintptr_t end = start + CardTable::kCardSize;
    space::ContinuousSpace* space =
        heap_->FindContinuousSpaceFromObject(reinterpret_cast<mirror::Object*>(start), false);
    DCHECK(space != nullptr);
    ContinuousSpaceBitmap* live_bitmap = space->GetLiveBitmap();
    live_bitmap->VisitMarkedRange(start, end, add_visitor);
    // Update the corresponding references for the card.
    auto found = references_.find(card);
    if (found == references_.end()) {
      // Don't add card for an empty reference array.
      if (!cards_references.empty()) {
        references_.Put(card, cards_references);
      }
    } else {
      if (cards_references.empty()) {
        references_.erase(found);
      } else {
        found->second = cards_references;
      }
    }
    if (has_target_reference) {
      // Keep this card for next time since it contains a GcRoot which matches the
      // ShouldAddReference criteria. This usually occurs for class loaders.
      new_cleared_cards.insert(card);
    }
  }
  cleared_cards_ = std::move(new_cleared_cards);
  size_t count = 0;
  for (auto it = references_.begin(); it != references_.end();) {
    std::vector<mirror::HeapReference<mirror::Object>*>& references = it->second;
    // Since there is no card mark for setting a reference to null, we check each reference.
    // If all of the references of a card are null then we can remove that card. This is racy
    // with the mutators, but handled by rescanning dirty cards.
    bool all_null = true;
    for (mirror::HeapReference<mirror::Object>* obj_ptr : references) {
      if (obj_ptr->AsMirrorPtr() != nullptr) {
        all_null = false;
        visitor->MarkHeapReference(obj_ptr, /*do_atomic_update=*/ false);
      }
    }
    count += references.size();
    if (!all_null) {
      ++it;
    } else {
      // All null references, erase the array from the set.
      it = references_.erase(it);
    }
  }
  if (VLOG_IS_ON(heap)) {
    VLOG(gc) << "Marked " << count << " references in mod union table";
  }
}

ModUnionTableCardCache::ModUnionTableCardCache(const std::string& name,
                                               Heap* heap,
                                               space::ContinuousSpace* space)
    : ModUnionTable(name, heap, space) {
  // Normally here we could use End() instead of Limit(), but for testing we may want to have a
  // mod-union table for a space which can still grow.
  if (!space->IsImageSpace()) {
    CHECK_ALIGNED(reinterpret_cast<uintptr_t>(space->Limit()), CardTable::kCardSize);
  }
  card_bitmap_.reset(CardBitmap::Create(
      "mod union bitmap", reinterpret_cast<uintptr_t>(space->Begin()),
      RoundUp(reinterpret_cast<uintptr_t>(space->Limit()), CardTable::kCardSize)));
}

class CardBitVisitor {
 public:
  CardBitVisitor(MarkObjectVisitor* visitor,
                 space::ContinuousSpace* space,
                 space::ContinuousSpace* immune_space,
                 ModUnionTable::CardBitmap* card_bitmap)
      : visitor_(visitor),
        space_(space),
        immune_space_(immune_space),
        bitmap_(space->GetLiveBitmap()),
        card_bitmap_(card_bitmap) {
    DCHECK(immune_space_ != nullptr);
  }

  void operator()(size_t bit_index) const {
    const uintptr_t start = card_bitmap_->AddrFromBitIndex(bit_index);
    DCHECK(space_->HasAddress(reinterpret_cast<mirror::Object*>(start)))
        << start << " " << *space_;
    bool reference_to_other_space = false;
    ModUnionScanImageRootVisitor scan_visitor(visitor_, space_, immune_space_,
                                              &reference_to_other_space);
    bitmap_->VisitMarkedRange(start, start + CardTable::kCardSize, scan_visitor);
    if (!reference_to_other_space) {
      // No non null reference to another space, clear the bit.
      card_bitmap_->ClearBit(bit_index);
    }
  }

 private:
  MarkObjectVisitor* const visitor_;
  space::ContinuousSpace* const space_;
  space::ContinuousSpace* const immune_space_;
  ContinuousSpaceBitmap* const bitmap_;
  ModUnionTable::CardBitmap* const card_bitmap_;
};

void ModUnionTableCardCache::ProcessCards() {
  CardTable* const card_table = GetHeap()->GetCardTable();
  ModUnionAddToCardBitmapVisitor visitor(card_bitmap_.get(), card_table);
  // Clear dirty cards in the this space and update the corresponding mod-union bits.
  card_table->ModifyCardsAtomic(space_->Begin(), space_->End(), AgeCardVisitor(), visitor);
}

void ModUnionTableCardCache::ClearTable() {
  card_bitmap_->Bitmap::Clear();
}

// Mark all references to the alloc space(s).
void ModUnionTableCardCache::UpdateAndMarkReferences(MarkObjectVisitor* visitor) {
  // TODO: Needs better support for multi-images? b/26317072
  space::ImageSpace* image_space =
      heap_->GetBootImageSpaces().empty() ? nullptr : heap_->GetBootImageSpaces()[0];
  // If we don't have an image space, just pass in space_ as the immune space. Pass in the same
  // space_ instead of image_space to avoid a null check in ModUnionUpdateObjectReferencesVisitor.
  CardBitVisitor bit_visitor(visitor, space_, image_space != nullptr ? image_space : space_,
      card_bitmap_.get());
  card_bitmap_->VisitSetBits(
      0, RoundUp(space_->Size(), CardTable::kCardSize) / CardTable::kCardSize, bit_visitor);
}

void ModUnionTableCardCache::VisitObjects(ObjectCallback callback, void* arg) {
  card_bitmap_->VisitSetBits(
      0,
      RoundUp(space_->Size(), CardTable::kCardSize) / CardTable::kCardSize,
      [this, callback, arg](size_t bit_index) {
        const uintptr_t start = card_bitmap_->AddrFromBitIndex(bit_index);
        DCHECK(space_->HasAddress(reinterpret_cast<mirror::Object*>(start)))
            << start << " " << *space_;
        space_->GetLiveBitmap()->VisitMarkedRange(start,
                                                  start + CardTable::kCardSize,
                                                  [callback, arg](mirror::Object* obj) {
          callback(obj, arg);
        });
      });
}

void ModUnionTableCardCache::Dump(std::ostream& os) {
  os << "ModUnionTable dirty cards: [";
  // TODO: Find cleaner way of doing this.
  for (uint8_t* addr = space_->Begin(); addr < AlignUp(space_->End(), CardTable::kCardSize);
      addr += CardTable::kCardSize) {
    if (card_bitmap_->Test(reinterpret_cast<uintptr_t>(addr))) {
      os << reinterpret_cast<void*>(addr) << "-"
         << reinterpret_cast<void*>(addr + CardTable::kCardSize) << "\n";
    }
  }
  os << "]";
}

void ModUnionTableCardCache::SetCards() {
  // Only clean up to the end since there cannot be any objects past the End() of the space.
  for (uint8_t* addr = space_->Begin(); addr < AlignUp(space_->End(), CardTable::kCardSize);
       addr += CardTable::kCardSize) {
    card_bitmap_->Set(reinterpret_cast<uintptr_t>(addr));
  }
}

bool ModUnionTableCardCache::ContainsCardFor(uintptr_t addr) {
  return card_bitmap_->Test(addr);
}

void ModUnionTableReferenceCache::SetCards() {
  for (uint8_t* addr = space_->Begin(); addr < AlignUp(space_->End(), CardTable::kCardSize);
       addr += CardTable::kCardSize) {
    cleared_cards_.insert(heap_->GetCardTable()->CardFromAddr(reinterpret_cast<void*>(addr)));
  }
}

bool ModUnionTableReferenceCache::ContainsCardFor(uintptr_t addr) {
  auto* card_ptr = heap_->GetCardTable()->CardFromAddr(reinterpret_cast<void*>(addr));
  return cleared_cards_.find(card_ptr) != cleared_cards_.end() ||
      references_.find(card_ptr) != references_.end();
}

}  // namespace accounting
}  // namespace gc
}  // namespace art
