blob: 79349740812f30325e5235d4af27617feb102b33 [file] [log] [blame]
Ian Rogers5d76c432011-10-31 21:42:49 -07001/*
Elliott Hughes2faa5f12012-01-30 14:42:07 -08002 * Copyright (C) 2011 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.
Ian Rogers5d76c432011-10-31 21:42:49 -070015 */
16
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_GC_ACCOUNTING_CARD_TABLE_H_
18#define ART_RUNTIME_GC_ACCOUNTING_CARD_TABLE_H_
Ian Rogers5d76c432011-10-31 21:42:49 -070019
Ian Rogers700a4022014-05-19 16:49:03 -070020#include <memory>
21
Ian Rogers719d1a32014-03-06 12:13:39 -080022#include "base/mutex.h"
Ian Rogers5d76c432011-10-31 21:42:49 -070023#include "globals.h"
Ian Rogers5d76c432011-10-31 21:42:49 -070024#include "mem_map.h"
Ian Rogers5d76c432011-10-31 21:42:49 -070025
26namespace art {
Ian Rogers1d54e732013-05-02 21:10:01 -070027
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080028namespace mirror {
Ian Rogers1d54e732013-05-02 21:10:01 -070029 class Object;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080030} // namespace mirror
Ian Rogers1d54e732013-05-02 21:10:01 -070031
32namespace gc {
33
34namespace space {
35 class ContinuousSpace;
36} // namespace space
37
Mathieu Chartier262e5ff2012-06-01 17:35:38 -070038class Heap;
Ian Rogers1d54e732013-05-02 21:10:01 -070039
40namespace accounting {
41
Mathieu Chartiera8e8f9c2014-04-09 14:51:05 -070042template<size_t kAlignment> class SpaceBitmap;
Ian Rogers5d76c432011-10-31 21:42:49 -070043
Elliott Hughes2faa5f12012-01-30 14:42:07 -080044// Maintain a card table from the the write barrier. All writes of
45// non-NULL values to heap addresses should go through an entry in
46// WriteBarrier, and from there to here.
Ian Rogers5d76c432011-10-31 21:42:49 -070047class CardTable {
48 public:
Mathieu Chartier7469ebf2012-09-24 16:28:36 -070049 static const size_t kCardShift = 7;
50 static const size_t kCardSize = (1 << kCardShift);
Mathieu Chartier9b3c3cd2013-08-12 17:41:54 -070051 static const uint8_t kCardClean = 0x0;
Mathieu Chartier7469ebf2012-09-24 16:28:36 -070052 static const uint8_t kCardDirty = 0x70;
53
Ian Rogers30fab402012-01-23 15:43:46 -080054 static CardTable* Create(const byte* heap_begin, size_t heap_capacity);
Ian Rogers5d76c432011-10-31 21:42:49 -070055
Ian Rogers30fab402012-01-23 15:43:46 -080056 // Set the card associated with the given address to GC_CARD_DIRTY.
Ian Rogers5d76c432011-10-31 21:42:49 -070057 void MarkCard(const void *addr) {
Elliott Hughes24edeb52012-06-18 15:29:46 -070058 byte* card_addr = CardFromAddr(addr);
Mathieu Chartier7469ebf2012-09-24 16:28:36 -070059 *card_addr = kCardDirty;
Ian Rogers5d76c432011-10-31 21:42:49 -070060 }
61
Ian Rogers30fab402012-01-23 15:43:46 -080062 // Is the object on a dirty card?
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080063 bool IsDirty(const mirror::Object* obj) const {
Mathieu Chartier4da7f2f2012-11-13 12:51:01 -080064 return GetCard(obj) == kCardDirty;
65 }
66
67 // Return the state of the card at an address.
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080068 byte GetCard(const mirror::Object* obj) const {
Mathieu Chartier4da7f2f2012-11-13 12:51:01 -080069 return *CardFromAddr(obj);
Ian Rogers5d76c432011-10-31 21:42:49 -070070 }
71
Mathieu Chartier7469ebf2012-09-24 16:28:36 -070072 // Visit and clear cards within memory range, only visits dirty cards.
Mathieu Chartierb43b7d42012-06-19 13:15:09 -070073 template <typename Visitor>
74 void VisitClear(const void* start, const void* end, const Visitor& visitor) {
75 byte* card_start = CardFromAddr(start);
76 byte* card_end = CardFromAddr(end);
Mathieu Chartier7469ebf2012-09-24 16:28:36 -070077 for (byte* it = card_start; it != card_end; ++it) {
78 if (*it == kCardDirty) {
79 *it = kCardClean;
80 visitor(it);
Mathieu Chartierb43b7d42012-06-19 13:15:09 -070081 }
82 }
83 }
84
Ian Rogers30fab402012-01-23 15:43:46 -080085 // Returns a value that when added to a heap address >> GC_CARD_SHIFT will address the appropriate
86 // card table byte. For convenience this value is cached in every Thread
87 byte* GetBiasedBegin() const {
88 return biased_begin_;
jeffhao39da0352011-11-04 14:58:55 -070089 }
90
Mathieu Chartierd22d5482012-11-06 17:14:12 -080091 /*
92 * Visitor is expected to take in a card and return the new value. When a value is modified, the
93 * modify visitor is called.
94 * visitor: The visitor which modifies the cards. Returns the new value for a card given an old
95 * value.
96 * modified: Whenever the visitor modifies a card, this visitor is called on the card. Enables
97 * us to know which cards got cleared.
98 */
99 template <typename Visitor, typename ModifiedVisitor>
100 void ModifyCardsAtomic(byte* scan_begin, byte* scan_end, const Visitor& visitor,
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800101 const ModifiedVisitor& modified);
Mathieu Chartierd22d5482012-11-06 17:14:12 -0800102
103 // For every dirty at least minumum age between begin and end invoke the visitor with the
Mathieu Chartier0f72e412013-09-06 16:40:01 -0700104 // specified argument. Returns how many cards the visitor was run on.
Mathieu Chartier184e3222013-08-03 14:02:57 -0700105 template <typename Visitor>
Mathieu Chartiera8e8f9c2014-04-09 14:51:05 -0700106 size_t Scan(SpaceBitmap<kObjectAlignment>* bitmap, byte* scan_begin, byte* scan_end,
107 const Visitor& visitor,
Mathieu Chartier0f72e412013-09-06 16:40:01 -0700108 const byte minimum_age = kCardDirty) const
Ian Rogersb726dcb2012-09-05 08:57:23 -0700109 EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_)
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800110 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Ian Rogers30fab402012-01-23 15:43:46 -0800111
Ian Rogers30fab402012-01-23 15:43:46 -0800112 // Assertion used to check the given address is covered by the card table
113 void CheckAddrIsInCardTable(const byte* addr) const;
114
Mathieu Chartier262e5ff2012-06-01 17:35:38 -0700115 // Resets all of the bytes in the card table to clean.
116 void ClearCardTable();
117
Mathieu Chartierb43b7d42012-06-19 13:15:09 -0700118 // Resets all of the bytes in the card table which do not map to the image space.
Ian Rogers1d54e732013-05-02 21:10:01 -0700119 void ClearSpaceCards(space::ContinuousSpace* space);
Ian Rogers5d76c432011-10-31 21:42:49 -0700120
Mathieu Chartierb43b7d42012-06-19 13:15:09 -0700121 // Returns the first address in the heap which maps to this card.
Mathieu Chartier94c32c52013-08-09 11:14:04 -0700122 void* AddrFromCard(const byte *card_addr) const ALWAYS_INLINE;
Ian Rogers5d76c432011-10-31 21:42:49 -0700123
Ian Rogers30fab402012-01-23 15:43:46 -0800124 // Returns the address of the relevant byte in the card table, given an address on the heap.
Mathieu Chartier94c32c52013-08-09 11:14:04 -0700125 byte* CardFromAddr(const void *addr) const ALWAYS_INLINE;
Ian Rogers5d76c432011-10-31 21:42:49 -0700126
Mathieu Chartier7469ebf2012-09-24 16:28:36 -0700127 bool AddrIsInCardTable(const void* addr) const;
128
Mathieu Chartiercc236d72012-07-20 10:29:05 -0700129 private:
130 CardTable(MemMap* begin, byte* biased_begin, size_t offset);
131
Ian Rogers30fab402012-01-23 15:43:46 -0800132 // Returns true iff the card table address is within the bounds of the card table.
Elliott Hughes24edeb52012-06-18 15:29:46 -0700133 bool IsValidCard(const byte* card_addr) const {
Ian Rogers30fab402012-01-23 15:43:46 -0800134 byte* begin = mem_map_->Begin() + offset_;
135 byte* end = mem_map_->End();
Elliott Hughes24edeb52012-06-18 15:29:46 -0700136 return card_addr >= begin && card_addr < end;
Ian Rogers5d76c432011-10-31 21:42:49 -0700137 }
138
Mathieu Chartier94c32c52013-08-09 11:14:04 -0700139 void CheckCardValid(byte* card) const ALWAYS_INLINE;
Mathieu Chartierd22d5482012-11-06 17:14:12 -0800140
Ian Rogers30fab402012-01-23 15:43:46 -0800141 // Verifies that all gray objects are on a dirty card.
Ian Rogers5d76c432011-10-31 21:42:49 -0700142 void VerifyCardTable();
143
Ian Rogers30fab402012-01-23 15:43:46 -0800144 // Mmapped pages for the card table
Ian Rogers700a4022014-05-19 16:49:03 -0700145 std::unique_ptr<MemMap> mem_map_;
Ian Rogers30fab402012-01-23 15:43:46 -0800146 // Value used to compute card table addresses from object addresses, see GetBiasedBegin
147 byte* const biased_begin_;
148 // Card table doesn't begin at the beginning of the mem_map_, instead it is displaced by offset
149 // to allow the byte value of biased_begin_ to equal GC_CARD_DIRTY
150 const size_t offset_;
Ian Rogers5d76c432011-10-31 21:42:49 -0700151};
152
Ian Rogers1d54e732013-05-02 21:10:01 -0700153} // namespace accounting
154} // namespace gc
Ian Rogers5d76c432011-10-31 21:42:49 -0700155} // namespace art
Ian Rogers1d54e732013-05-02 21:10:01 -0700156
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700157#endif // ART_RUNTIME_GC_ACCOUNTING_CARD_TABLE_H_