xref: /aosp_15_r20/art/runtime/gc/accounting/bitmap.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_GC_ACCOUNTING_BITMAP_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_GC_ACCOUNTING_BITMAP_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include <limits.h>
21*795d594fSAndroid Build Coastguard Worker #include <stdint.h>
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker #include <memory>
24*795d594fSAndroid Build Coastguard Worker #include <set>
25*795d594fSAndroid Build Coastguard Worker #include <vector>
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/locks.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/mem_map.h"
30*795d594fSAndroid Build Coastguard Worker #include "runtime_globals.h"
31*795d594fSAndroid Build Coastguard Worker 
32*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker namespace gc {
35*795d594fSAndroid Build Coastguard Worker namespace accounting {
36*795d594fSAndroid Build Coastguard Worker 
37*795d594fSAndroid Build Coastguard Worker // TODO: Use this code to implement SpaceBitmap.
38*795d594fSAndroid Build Coastguard Worker class Bitmap {
39*795d594fSAndroid Build Coastguard Worker  public:
40*795d594fSAndroid Build Coastguard Worker   // Create and initialize a bitmap with size num_bits. Storage is allocated with a MemMap.
41*795d594fSAndroid Build Coastguard Worker   static Bitmap* Create(const std::string& name, size_t num_bits);
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker   // Initialize a space bitmap using the provided mem_map as the live bits. Takes ownership of the
44*795d594fSAndroid Build Coastguard Worker   // mem map. The address range covered starts at heap_begin and is of size equal to heap_capacity.
45*795d594fSAndroid Build Coastguard Worker   // Objects are kAlignement-aligned.
46*795d594fSAndroid Build Coastguard Worker   static Bitmap* CreateFromMemMap(MemMap&& mem_map, size_t num_bits);
47*795d594fSAndroid Build Coastguard Worker 
48*795d594fSAndroid Build Coastguard Worker   // offset is the difference from base to a index.
BitIndexToWordIndex(uintptr_t offset)49*795d594fSAndroid Build Coastguard Worker   static ALWAYS_INLINE constexpr size_t BitIndexToWordIndex(uintptr_t offset) {
50*795d594fSAndroid Build Coastguard Worker     return offset / kBitsPerBitmapWord;
51*795d594fSAndroid Build Coastguard Worker   }
52*795d594fSAndroid Build Coastguard Worker 
53*795d594fSAndroid Build Coastguard Worker   template<typename T>
WordIndexToBitIndex(T word_index)54*795d594fSAndroid Build Coastguard Worker   static ALWAYS_INLINE constexpr T WordIndexToBitIndex(T word_index) {
55*795d594fSAndroid Build Coastguard Worker     return static_cast<T>(word_index * kBitsPerBitmapWord);
56*795d594fSAndroid Build Coastguard Worker   }
57*795d594fSAndroid Build Coastguard Worker 
BitIndexToMask(uintptr_t bit_index)58*795d594fSAndroid Build Coastguard Worker   static ALWAYS_INLINE constexpr uintptr_t BitIndexToMask(uintptr_t bit_index) {
59*795d594fSAndroid Build Coastguard Worker     return static_cast<uintptr_t>(1) << (bit_index % kBitsPerBitmapWord);
60*795d594fSAndroid Build Coastguard Worker   }
61*795d594fSAndroid Build Coastguard Worker 
SetBit(size_t bit_index)62*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool SetBit(size_t bit_index) {
63*795d594fSAndroid Build Coastguard Worker     return ModifyBit<true>(bit_index);
64*795d594fSAndroid Build Coastguard Worker   }
65*795d594fSAndroid Build Coastguard Worker 
ClearBit(size_t bit_index)66*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool ClearBit(size_t bit_index) {
67*795d594fSAndroid Build Coastguard Worker     return ModifyBit<false>(bit_index);
68*795d594fSAndroid Build Coastguard Worker   }
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool TestBit(size_t bit_index) const;
71*795d594fSAndroid Build Coastguard Worker 
72*795d594fSAndroid Build Coastguard Worker   // Returns true if the bit_index was previously set.
73*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool AtomicTestAndSetBit(size_t bit_index);
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker   // Fill the bitmap with zeroes.  Returns the bitmap's memory to the system as a side-effect.
76*795d594fSAndroid Build Coastguard Worker   void Clear();
77*795d594fSAndroid Build Coastguard Worker 
78*795d594fSAndroid Build Coastguard Worker   // Visit the all the set bits range [visit_begin, visit_end) where visit_begin and visit_end are
79*795d594fSAndroid Build Coastguard Worker   // bit indices visitor is called with the index of each set bit.
80*795d594fSAndroid Build Coastguard Worker   template <typename Visitor>
81*795d594fSAndroid Build Coastguard Worker   void VisitSetBits(uintptr_t visit_begin, size_t visit_end, const Visitor& visitor) const;
82*795d594fSAndroid Build Coastguard Worker 
83*795d594fSAndroid Build Coastguard Worker   void CopyFrom(Bitmap* source_bitmap);
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker   // Starting address of our internal storage.
Begin()86*795d594fSAndroid Build Coastguard Worker   uintptr_t* Begin() const {
87*795d594fSAndroid Build Coastguard Worker     return bitmap_begin_;
88*795d594fSAndroid Build Coastguard Worker   }
89*795d594fSAndroid Build Coastguard Worker 
90*795d594fSAndroid Build Coastguard Worker   // Size of our bitmap in bits.
BitmapSize()91*795d594fSAndroid Build Coastguard Worker   size_t BitmapSize() const { return bitmap_numbits_; }
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker   // Check that a bit index is valid with a DCHECK.
CheckValidBitIndex(size_t bit_index)94*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE void CheckValidBitIndex(size_t bit_index) const {
95*795d594fSAndroid Build Coastguard Worker     DCHECK_LT(bit_index, BitmapSize());
96*795d594fSAndroid Build Coastguard Worker   }
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker   std::string Dump() const;
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker  protected:
101*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kBitsPerBitmapWord = kBitsPerIntPtrT;
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker   Bitmap(MemMap&& mem_map, size_t bitmap_size);
104*795d594fSAndroid Build Coastguard Worker   ~Bitmap();
105*795d594fSAndroid Build Coastguard Worker 
106*795d594fSAndroid Build Coastguard Worker   // Allocate the mem-map for a bitmap based on how many bits are required.
107*795d594fSAndroid Build Coastguard Worker   static MemMap AllocateMemMap(const std::string& name, size_t num_bits);
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker   template<bool kSetBit>
110*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool ModifyBit(uintptr_t bit_index);
111*795d594fSAndroid Build Coastguard Worker 
112*795d594fSAndroid Build Coastguard Worker   // Backing storage for bitmap. This is interpreted as an array of
113*795d594fSAndroid Build Coastguard Worker   // kBitsPerBitmapWord-sized integers, with bits assigned in each word little
114*795d594fSAndroid Build Coastguard Worker   // endian first.
115*795d594fSAndroid Build Coastguard Worker   MemMap mem_map_;
116*795d594fSAndroid Build Coastguard Worker 
117*795d594fSAndroid Build Coastguard Worker   // This bitmap itself, word sized for efficiency in scanning.
118*795d594fSAndroid Build Coastguard Worker   uintptr_t* const bitmap_begin_;
119*795d594fSAndroid Build Coastguard Worker 
120*795d594fSAndroid Build Coastguard Worker   // Number of bits in the bitmap.
121*795d594fSAndroid Build Coastguard Worker   size_t bitmap_numbits_;
122*795d594fSAndroid Build Coastguard Worker 
123*795d594fSAndroid Build Coastguard Worker  private:
124*795d594fSAndroid Build Coastguard Worker   DISALLOW_IMPLICIT_CONSTRUCTORS(Bitmap);
125*795d594fSAndroid Build Coastguard Worker };
126*795d594fSAndroid Build Coastguard Worker 
127*795d594fSAndroid Build Coastguard Worker // One bit per kAlignment in range [start, end)
128*795d594fSAndroid Build Coastguard Worker template<size_t kAlignment>
129*795d594fSAndroid Build Coastguard Worker class MemoryRangeBitmap : public Bitmap {
130*795d594fSAndroid Build Coastguard Worker  public:
131*795d594fSAndroid Build Coastguard Worker   static MemoryRangeBitmap* Create(
132*795d594fSAndroid Build Coastguard Worker       const std::string& name, uintptr_t cover_begin, uintptr_t cover_end);
133*795d594fSAndroid Build Coastguard Worker   static MemoryRangeBitmap* CreateFromMemMap(
134*795d594fSAndroid Build Coastguard Worker       MemMap&& mem_map, uintptr_t cover_begin, size_t num_bits);
135*795d594fSAndroid Build Coastguard Worker 
SetBitmapSize(size_t bytes)136*795d594fSAndroid Build Coastguard Worker   void SetBitmapSize(size_t bytes) {
137*795d594fSAndroid Build Coastguard Worker     CHECK_ALIGNED(bytes, kAlignment);
138*795d594fSAndroid Build Coastguard Worker     bitmap_numbits_ = bytes / kAlignment;
139*795d594fSAndroid Build Coastguard Worker     size_t rounded_size =
140*795d594fSAndroid Build Coastguard Worker         RoundUp(bitmap_numbits_, kBitsPerBitmapWord) / kBitsPerBitmapWord * sizeof(uintptr_t);
141*795d594fSAndroid Build Coastguard Worker     mem_map_.SetSize(rounded_size);
142*795d594fSAndroid Build Coastguard Worker   }
143*795d594fSAndroid Build Coastguard Worker 
144*795d594fSAndroid Build Coastguard Worker   // Beginning of the memory range that the bitmap covers.
CoverBegin()145*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE uintptr_t CoverBegin() const {
146*795d594fSAndroid Build Coastguard Worker     return cover_begin_;
147*795d594fSAndroid Build Coastguard Worker   }
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker   // End of the memory range that the bitmap covers.
CoverEnd()150*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE uintptr_t CoverEnd() const {
151*795d594fSAndroid Build Coastguard Worker     return cover_begin_ + kAlignment * BitmapSize();
152*795d594fSAndroid Build Coastguard Worker   }
153*795d594fSAndroid Build Coastguard Worker 
154*795d594fSAndroid Build Coastguard Worker   // Return the address associated with a bit index.
AddrFromBitIndex(size_t bit_index)155*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE uintptr_t AddrFromBitIndex(size_t bit_index) const {
156*795d594fSAndroid Build Coastguard Worker     const uintptr_t addr = CoverBegin() + bit_index * kAlignment;
157*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(BitIndexFromAddr(addr), bit_index);
158*795d594fSAndroid Build Coastguard Worker     return addr;
159*795d594fSAndroid Build Coastguard Worker   }
160*795d594fSAndroid Build Coastguard Worker 
161*795d594fSAndroid Build Coastguard Worker   // Return the bit index associated with an address .
BitIndexFromAddr(uintptr_t addr)162*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE uintptr_t BitIndexFromAddr(uintptr_t addr) const {
163*795d594fSAndroid Build Coastguard Worker     uintptr_t result = (addr - CoverBegin()) / kAlignment;
164*795d594fSAndroid Build Coastguard Worker     DCHECK(result < BitmapSize()) << CoverBegin() << " <= " <<  addr << " < " << CoverEnd();
165*795d594fSAndroid Build Coastguard Worker     return result;
166*795d594fSAndroid Build Coastguard Worker   }
167*795d594fSAndroid Build Coastguard Worker 
HasAddress(const uintptr_t addr)168*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool HasAddress(const uintptr_t addr) const {
169*795d594fSAndroid Build Coastguard Worker     // Don't use BitIndexFromAddr() here as the addr passed to this function
170*795d594fSAndroid Build Coastguard Worker     // could be outside the range. If addr < cover_begin_, then the result
171*795d594fSAndroid Build Coastguard Worker     // underflows to some very large value past the end of the bitmap.
172*795d594fSAndroid Build Coastguard Worker     // Therefore, all operations are unsigned here.
173*795d594fSAndroid Build Coastguard Worker     bool ret = (addr - CoverBegin()) / kAlignment < BitmapSize();
174*795d594fSAndroid Build Coastguard Worker     if (ret) {
175*795d594fSAndroid Build Coastguard Worker       DCHECK(CoverBegin() <= addr && addr < CoverEnd())
176*795d594fSAndroid Build Coastguard Worker           << CoverBegin() << " <= " <<  addr << " < " << CoverEnd();
177*795d594fSAndroid Build Coastguard Worker     }
178*795d594fSAndroid Build Coastguard Worker     return ret;
179*795d594fSAndroid Build Coastguard Worker   }
180*795d594fSAndroid Build Coastguard Worker 
Set(uintptr_t addr)181*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool Set(uintptr_t addr) {
182*795d594fSAndroid Build Coastguard Worker     return SetBit(BitIndexFromAddr(addr));
183*795d594fSAndroid Build Coastguard Worker   }
184*795d594fSAndroid Build Coastguard Worker 
Clear(uintptr_t addr)185*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool Clear(uintptr_t addr) {
186*795d594fSAndroid Build Coastguard Worker     return ClearBit(BitIndexFromAddr(addr));
187*795d594fSAndroid Build Coastguard Worker   }
188*795d594fSAndroid Build Coastguard Worker 
Test(uintptr_t addr)189*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool Test(uintptr_t addr) const {
190*795d594fSAndroid Build Coastguard Worker     return TestBit(BitIndexFromAddr(addr));
191*795d594fSAndroid Build Coastguard Worker   }
192*795d594fSAndroid Build Coastguard Worker 
193*795d594fSAndroid Build Coastguard Worker   // Returns true if the object was previously set.
AtomicTestAndSet(uintptr_t addr)194*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool AtomicTestAndSet(uintptr_t addr) {
195*795d594fSAndroid Build Coastguard Worker     return AtomicTestAndSetBit(BitIndexFromAddr(addr));
196*795d594fSAndroid Build Coastguard Worker   }
197*795d594fSAndroid Build Coastguard Worker 
198*795d594fSAndroid Build Coastguard Worker  private:
MemoryRangeBitmap(MemMap && mem_map,uintptr_t begin,size_t num_bits)199*795d594fSAndroid Build Coastguard Worker   MemoryRangeBitmap(MemMap&& mem_map, uintptr_t begin, size_t num_bits)
200*795d594fSAndroid Build Coastguard Worker       : Bitmap(std::move(mem_map), num_bits),
201*795d594fSAndroid Build Coastguard Worker         cover_begin_(begin) {}
202*795d594fSAndroid Build Coastguard Worker 
203*795d594fSAndroid Build Coastguard Worker   uintptr_t const cover_begin_;
204*795d594fSAndroid Build Coastguard Worker 
205*795d594fSAndroid Build Coastguard Worker   DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryRangeBitmap);
206*795d594fSAndroid Build Coastguard Worker };
207*795d594fSAndroid Build Coastguard Worker 
208*795d594fSAndroid Build Coastguard Worker }  // namespace accounting
209*795d594fSAndroid Build Coastguard Worker }  // namespace gc
210*795d594fSAndroid Build Coastguard Worker }  // namespace art
211*795d594fSAndroid Build Coastguard Worker 
212*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_GC_ACCOUNTING_BITMAP_H_
213