summaryrefslogtreecommitdiffstats
path: root/runtime/gc/accounting/card_table.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/gc/accounting/card_table.h')
-rw-r--r--runtime/gc/accounting/card_table.h156
1 files changed, 156 insertions, 0 deletions
diff --git a/runtime/gc/accounting/card_table.h b/runtime/gc/accounting/card_table.h
new file mode 100644
index 0000000..cf85d15
--- /dev/null
+++ b/runtime/gc/accounting/card_table.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#ifndef ART_SRC_GC_CARDTABLE_H_
+#define ART_SRC_GC_CARDTABLE_H_
+
+#include "globals.h"
+#include "locks.h"
+#include "mem_map.h"
+#include "UniquePtr.h"
+
+namespace art {
+
+namespace mirror {
+ class Object;
+} // namespace mirror
+
+namespace gc {
+
+namespace space {
+ class ContinuousSpace;
+} // namespace space
+
+class Heap;
+
+namespace accounting {
+
+class SpaceBitmap;
+
+// Maintain a card table from the the write barrier. All writes of
+// non-NULL values to heap addresses should go through an entry in
+// WriteBarrier, and from there to here.
+class CardTable {
+ public:
+ static const size_t kCardShift = 7;
+ static const size_t kCardSize = (1 << kCardShift);
+ static const uint8_t kCardClean = 0x0;
+ static const uint8_t kCardDirty = 0x70;
+
+ static CardTable* Create(const byte* heap_begin, size_t heap_capacity);
+
+ // Set the card associated with the given address to GC_CARD_DIRTY.
+ void MarkCard(const void *addr) {
+ byte* card_addr = CardFromAddr(addr);
+ *card_addr = kCardDirty;
+ }
+
+ // Is the object on a dirty card?
+ bool IsDirty(const mirror::Object* obj) const {
+ return GetCard(obj) == kCardDirty;
+ }
+
+ // Return the state of the card at an address.
+ byte GetCard(const mirror::Object* obj) const {
+ return *CardFromAddr(obj);
+ }
+
+ // Visit and clear cards within memory range, only visits dirty cards.
+ template <typename Visitor>
+ void VisitClear(const void* start, const void* end, const Visitor& visitor) {
+ byte* card_start = CardFromAddr(start);
+ byte* card_end = CardFromAddr(end);
+ for (byte* it = card_start; it != card_end; ++it) {
+ if (*it == kCardDirty) {
+ *it = kCardClean;
+ visitor(it);
+ }
+ }
+ }
+
+ // Returns a value that when added to a heap address >> GC_CARD_SHIFT will address the appropriate
+ // card table byte. For convenience this value is cached in every Thread
+ byte* GetBiasedBegin() const {
+ return biased_begin_;
+ }
+
+ /*
+ * Visitor is expected to take in a card and return the new value. When a value is modified, the
+ * modify visitor is called.
+ * visitor: The visitor which modifies the cards. Returns the new value for a card given an old
+ * value.
+ * modified: Whenever the visitor modifies a card, this visitor is called on the card. Enables
+ * us to know which cards got cleared.
+ */
+ template <typename Visitor, typename ModifiedVisitor>
+ void ModifyCardsAtomic(byte* scan_begin, byte* scan_end, const Visitor& visitor,
+ const ModifiedVisitor& modified);
+
+ // For every dirty at least minumum age between begin and end invoke the visitor with the
+ // specified argument.
+ template <typename Visitor, typename FingerVisitor>
+ void Scan(SpaceBitmap* bitmap, byte* scan_begin, byte* scan_end,
+ const Visitor& visitor, const FingerVisitor& finger_visitor,
+ const byte minimum_age = kCardDirty) const
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ // Assertion used to check the given address is covered by the card table
+ void CheckAddrIsInCardTable(const byte* addr) const;
+
+ // Resets all of the bytes in the card table to clean.
+ void ClearCardTable();
+
+ // Resets all of the bytes in the card table which do not map to the image space.
+ void ClearSpaceCards(space::ContinuousSpace* space);
+
+ // Returns the first address in the heap which maps to this card.
+ void* AddrFromCard(const byte *card_addr) const;
+
+ // Returns the address of the relevant byte in the card table, given an address on the heap.
+ byte* CardFromAddr(const void *addr) const;
+
+ bool AddrIsInCardTable(const void* addr) const;
+
+ private:
+ CardTable(MemMap* begin, byte* biased_begin, size_t offset);
+
+ // Returns true iff the card table address is within the bounds of the card table.
+ bool IsValidCard(const byte* card_addr) const {
+ byte* begin = mem_map_->Begin() + offset_;
+ byte* end = mem_map_->End();
+ return card_addr >= begin && card_addr < end;
+ }
+
+ void CheckCardValid(byte* card) const;
+
+ // Verifies that all gray objects are on a dirty card.
+ void VerifyCardTable();
+
+ // Mmapped pages for the card table
+ UniquePtr<MemMap> mem_map_;
+ // Value used to compute card table addresses from object addresses, see GetBiasedBegin
+ byte* const biased_begin_;
+ // Card table doesn't begin at the beginning of the mem_map_, instead it is displaced by offset
+ // to allow the byte value of biased_begin_ to equal GC_CARD_DIRTY
+ const size_t offset_;
+};
+
+} // namespace accounting
+} // namespace gc
+} // namespace art
+
+#endif // ART_SRC_GC_CARDTABLE_H_