blob: 68ef15d0cf0ea39b1b4cbd643d0e2213416e2c27 [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
25namespace art {
Ian Rogers1d54e732013-05-02 21:10:01 -070026
Vladimir Marko3481ba22015-04-13 12:22:36 +010027class MemMap;
28
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080029namespace mirror {
Ian Rogers1d54e732013-05-02 21:10:01 -070030 class Object;
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080031} // namespace mirror
Ian Rogers1d54e732013-05-02 21:10:01 -070032
33namespace gc {
34
35namespace space {
36 class ContinuousSpace;
37} // namespace space
38
Mathieu Chartier262e5ff2012-06-01 17:35:38 -070039class Heap;
Ian Rogers1d54e732013-05-02 21:10:01 -070040
41namespace accounting {
42
Mathieu Chartiera8e8f9c2014-04-09 14:51:05 -070043template<size_t kAlignment> class SpaceBitmap;
Ian Rogers5d76c432011-10-31 21:42:49 -070044
Elliott Hughes2faa5f12012-01-30 14:42:07 -080045// Maintain a card table from the the write barrier. All writes of
Mathieu Chartier2cebb242015-04-21 16:50:40 -070046// non-null values to heap addresses should go through an entry in
Elliott Hughes2faa5f12012-01-30 14:42:07 -080047// WriteBarrier, and from there to here.
Ian Rogers5d76c432011-10-31 21:42:49 -070048class CardTable {
49 public:
Mathieu Chartier2c265012014-08-05 18:15:56 -070050 static constexpr size_t kCardShift = 7;
51 static constexpr size_t kCardSize = 1 << kCardShift;
52 static constexpr uint8_t kCardClean = 0x0;
53 static constexpr uint8_t kCardDirty = 0x70;
Mathieu Chartier7469ebf2012-09-24 16:28:36 -070054
Ian Rogers13735952014-10-08 12:43:28 -070055 static CardTable* Create(const uint8_t* heap_begin, size_t heap_capacity);
Vladimir Marko3481ba22015-04-13 12:22:36 +010056 ~CardTable();
Ian Rogers5d76c432011-10-31 21:42:49 -070057
Ian Rogers30fab402012-01-23 15:43:46 -080058 // Set the card associated with the given address to GC_CARD_DIRTY.
Mathieu Chartier2d2621a2014-10-23 16:48:06 -070059 ALWAYS_INLINE void MarkCard(const void *addr) {
60 *CardFromAddr(addr) = kCardDirty;
Ian Rogers5d76c432011-10-31 21:42:49 -070061 }
62
Ian Rogers30fab402012-01-23 15:43:46 -080063 // Is the object on a dirty card?
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080064 bool IsDirty(const mirror::Object* obj) const {
Mathieu Chartier4da7f2f2012-11-13 12:51:01 -080065 return GetCard(obj) == kCardDirty;
66 }
67
68 // Return the state of the card at an address.
Ian Rogers13735952014-10-08 12:43:28 -070069 uint8_t GetCard(const mirror::Object* obj) const {
Mathieu Chartier4da7f2f2012-11-13 12:51:01 -080070 return *CardFromAddr(obj);
Ian Rogers5d76c432011-10-31 21:42:49 -070071 }
72
Mathieu Chartier7469ebf2012-09-24 16:28:36 -070073 // Visit and clear cards within memory range, only visits dirty cards.
Mathieu Chartierb43b7d42012-06-19 13:15:09 -070074 template <typename Visitor>
75 void VisitClear(const void* start, const void* end, const Visitor& visitor) {
Ian Rogers13735952014-10-08 12:43:28 -070076 uint8_t* card_start = CardFromAddr(start);
77 uint8_t* card_end = CardFromAddr(end);
78 for (uint8_t* it = card_start; it != card_end; ++it) {
Mathieu Chartier7469ebf2012-09-24 16:28:36 -070079 if (*it == kCardDirty) {
80 *it = kCardClean;
81 visitor(it);
Mathieu Chartierb43b7d42012-06-19 13:15:09 -070082 }
83 }
84 }
85
Ian Rogers30fab402012-01-23 15:43:46 -080086 // Returns a value that when added to a heap address >> GC_CARD_SHIFT will address the appropriate
87 // card table byte. For convenience this value is cached in every Thread
Ian Rogers13735952014-10-08 12:43:28 -070088 uint8_t* GetBiasedBegin() const {
Ian Rogers30fab402012-01-23 15:43:46 -080089 return biased_begin_;
jeffhao39da0352011-11-04 14:58:55 -070090 }
91
Mathieu Chartierd22d5482012-11-06 17:14:12 -080092 /*
93 * Visitor is expected to take in a card and return the new value. When a value is modified, the
94 * modify visitor is called.
95 * visitor: The visitor which modifies the cards. Returns the new value for a card given an old
96 * value.
97 * modified: Whenever the visitor modifies a card, this visitor is called on the card. Enables
98 * us to know which cards got cleared.
99 */
100 template <typename Visitor, typename ModifiedVisitor>
Mathieu Chartier6e6078a2016-10-24 15:45:41 -0700101 void ModifyCardsAtomic(uint8_t* scan_begin,
102 uint8_t* scan_end,
103 const Visitor& visitor,
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800104 const ModifiedVisitor& modified);
Mathieu Chartierd22d5482012-11-06 17:14:12 -0800105
106 // For every dirty at least minumum age between begin and end invoke the visitor with the
Mathieu Chartier0f72e412013-09-06 16:40:01 -0700107 // specified argument. Returns how many cards the visitor was run on.
Lei Li727b2942015-01-15 11:26:34 +0800108 template <bool kClearCard, typename Visitor>
Mathieu Chartier6e6078a2016-10-24 15:45:41 -0700109 size_t Scan(SpaceBitmap<kObjectAlignment>* bitmap,
110 uint8_t* scan_begin,
111 uint8_t* scan_end,
Mathieu Chartiera8e8f9c2014-04-09 14:51:05 -0700112 const Visitor& visitor,
Mathieu Chartier6e6078a2016-10-24 15:45:41 -0700113 const uint8_t minimum_age = kCardDirty)
Mathieu Chartier90443472015-07-16 20:32:27 -0700114 REQUIRES(Locks::heap_bitmap_lock_)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700115 REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers30fab402012-01-23 15:43:46 -0800116
Ian Rogers30fab402012-01-23 15:43:46 -0800117 // Assertion used to check the given address is covered by the card table
Ian Rogers13735952014-10-08 12:43:28 -0700118 void CheckAddrIsInCardTable(const uint8_t* addr) const;
Ian Rogers30fab402012-01-23 15:43:46 -0800119
Mathieu Chartier262e5ff2012-06-01 17:35:38 -0700120 // Resets all of the bytes in the card table to clean.
121 void ClearCardTable();
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800122
123 // Clear a range of cards that covers start to end, start and end must be aligned to kCardSize.
Lei Li4add3b42015-01-15 11:55:26 +0800124 void ClearCardRange(uint8_t* start, uint8_t* end);
Mathieu Chartier262e5ff2012-06-01 17:35:38 -0700125
Mathieu Chartierb43b7d42012-06-19 13:15:09 -0700126 // Returns the first address in the heap which maps to this card.
Ian Rogers13735952014-10-08 12:43:28 -0700127 void* AddrFromCard(const uint8_t *card_addr) const ALWAYS_INLINE;
Ian Rogers5d76c432011-10-31 21:42:49 -0700128
Ian Rogers30fab402012-01-23 15:43:46 -0800129 // Returns the address of the relevant byte in the card table, given an address on the heap.
Ian Rogers13735952014-10-08 12:43:28 -0700130 uint8_t* CardFromAddr(const void *addr) const ALWAYS_INLINE;
Ian Rogers5d76c432011-10-31 21:42:49 -0700131
Mathieu Chartier7469ebf2012-09-24 16:28:36 -0700132 bool AddrIsInCardTable(const void* addr) const;
133
Mathieu Chartiercc236d72012-07-20 10:29:05 -0700134 private:
Ian Rogers13735952014-10-08 12:43:28 -0700135 CardTable(MemMap* begin, uint8_t* biased_begin, size_t offset);
Mathieu Chartiercc236d72012-07-20 10:29:05 -0700136
Ian Rogers30fab402012-01-23 15:43:46 -0800137 // Returns true iff the card table address is within the bounds of the card table.
Vladimir Marko3481ba22015-04-13 12:22:36 +0100138 bool IsValidCard(const uint8_t* card_addr) const ALWAYS_INLINE;
Ian Rogers5d76c432011-10-31 21:42:49 -0700139
Ian Rogers13735952014-10-08 12:43:28 -0700140 void CheckCardValid(uint8_t* card) const ALWAYS_INLINE;
Mathieu Chartierd22d5482012-11-06 17:14:12 -0800141
Ian Rogers30fab402012-01-23 15:43:46 -0800142 // Verifies that all gray objects are on a dirty card.
Ian Rogers5d76c432011-10-31 21:42:49 -0700143 void VerifyCardTable();
144
Ian Rogers30fab402012-01-23 15:43:46 -0800145 // Mmapped pages for the card table
Ian Rogers700a4022014-05-19 16:49:03 -0700146 std::unique_ptr<MemMap> mem_map_;
Ian Rogers30fab402012-01-23 15:43:46 -0800147 // Value used to compute card table addresses from object addresses, see GetBiasedBegin
Ian Rogers13735952014-10-08 12:43:28 -0700148 uint8_t* const biased_begin_;
Ian Rogers30fab402012-01-23 15:43:46 -0800149 // Card table doesn't begin at the beginning of the mem_map_, instead it is displaced by offset
150 // to allow the byte value of biased_begin_ to equal GC_CARD_DIRTY
151 const size_t offset_;
Mathieu Chartier3130cdf2015-05-03 15:20:23 -0700152
153 DISALLOW_IMPLICIT_CONSTRUCTORS(CardTable);
Ian Rogers5d76c432011-10-31 21:42:49 -0700154};
155
Ian Rogers1d54e732013-05-02 21:10:01 -0700156} // namespace accounting
157} // namespace gc
Ian Rogers5d76c432011-10-31 21:42:49 -0700158} // namespace art
Ian Rogers1d54e732013-05-02 21:10:01 -0700159
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700160#endif // ART_RUNTIME_GC_ACCOUNTING_CARD_TABLE_H_