• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.
15  */
16 
17 #ifndef ART_RUNTIME_GC_ACCOUNTING_BITMAP_H_
18 #define ART_RUNTIME_GC_ACCOUNTING_BITMAP_H_
19 
20 #include <limits.h>
21 #include <stdint.h>
22 #include <memory>
23 #include <set>
24 #include <vector>
25 
26 #include "base/mutex.h"
27 #include "globals.h"
28 
29 namespace art {
30 
31 class MemMap;
32 
33 namespace gc {
34 namespace accounting {
35 
36 // TODO: Use this code to implement SpaceBitmap.
37 class Bitmap {
38  public:
39   // Create and initialize a bitmap with size num_bits. Storage is allocated with a MemMap.
40   static Bitmap* Create(const std::string& name, size_t num_bits);
41 
42   // Initialize a space bitmap using the provided mem_map as the live bits. Takes ownership of the
43   // mem map. The address range covered starts at heap_begin and is of size equal to heap_capacity.
44   // Objects are kAlignement-aligned.
45   static Bitmap* CreateFromMemMap(MemMap* mem_map, size_t num_bits);
46 
47   // offset is the difference from base to a index.
BitIndexToWordIndex(uintptr_t offset)48   static ALWAYS_INLINE constexpr size_t BitIndexToWordIndex(uintptr_t offset) {
49     return offset / kBitsPerBitmapWord;
50   }
51 
52   template<typename T>
WordIndexToBitIndex(T word_index)53   static ALWAYS_INLINE constexpr T WordIndexToBitIndex(T word_index) {
54     return static_cast<T>(word_index * kBitsPerBitmapWord);
55   }
56 
BitIndexToMask(uintptr_t bit_index)57   static ALWAYS_INLINE constexpr uintptr_t BitIndexToMask(uintptr_t bit_index) {
58     return static_cast<uintptr_t>(1) << (bit_index % kBitsPerBitmapWord);
59   }
60 
SetBit(size_t bit_index)61   ALWAYS_INLINE bool SetBit(size_t bit_index) {
62     return ModifyBit<true>(bit_index);
63   }
64 
ClearBit(size_t bit_index)65   ALWAYS_INLINE bool ClearBit(size_t bit_index) {
66     return ModifyBit<false>(bit_index);
67   }
68 
69   ALWAYS_INLINE bool TestBit(size_t bit_index) const;
70 
71   // Returns true if the bit_index was previously set.
72   ALWAYS_INLINE bool AtomicTestAndSetBit(size_t bit_index);
73 
74   // Fill the bitmap with zeroes.  Returns the bitmap's memory to the system as a side-effect.
75   void Clear();
76 
77   // Visit the all the set bits range [visit_begin, visit_end) where visit_begin and visit_end are
78   // bit indices visitor is called with the index of each set bit.
79   template <typename Visitor>
80   void VisitSetBits(uintptr_t visit_begin, size_t visit_end, const Visitor& visitor) const;
81 
82   void CopyFrom(Bitmap* source_bitmap);
83 
84   // Starting address of our internal storage.
Begin()85   uintptr_t* Begin() {
86     return bitmap_begin_;
87   }
88 
89   // Size of our bitmap in bits.
BitmapSize()90   size_t BitmapSize() const {
91     return bitmap_size_;
92   }
93 
94   // Check that a bit index is valid with a DCHECK.
CheckValidBitIndex(size_t bit_index)95   ALWAYS_INLINE void CheckValidBitIndex(size_t bit_index) const {
96     DCHECK_LT(bit_index, BitmapSize());
97   }
98 
99   std::string Dump() const;
100 
101  protected:
102   static constexpr size_t kBitsPerBitmapWord = sizeof(uintptr_t) * kBitsPerByte;
103 
104   Bitmap(MemMap* mem_map, size_t bitmap_size);
105   ~Bitmap();
106 
107   // Allocate the mem-map for a bitmap based on how many bits are required.
108   static MemMap* AllocateMemMap(const std::string& name, size_t num_bits);
109 
110   template<bool kSetBit>
111   ALWAYS_INLINE bool ModifyBit(uintptr_t bit_index);
112 
113   // Backing storage for bitmap.
114   std::unique_ptr<MemMap> mem_map_;
115 
116   // This bitmap itself, word sized for efficiency in scanning.
117   uintptr_t* const bitmap_begin_;
118 
119   // Number of bits in the bitmap.
120   const size_t bitmap_size_;
121 
122  private:
123   DISALLOW_IMPLICIT_CONSTRUCTORS(Bitmap);
124 };
125 
126 // One bit per kAlignment in range (start, end]
127 template<size_t kAlignment>
128 class MemoryRangeBitmap : public Bitmap {
129  public:
130   static MemoryRangeBitmap* Create(const std::string& name, uintptr_t cover_begin,
131                                    uintptr_t cover_end);
132   static MemoryRangeBitmap* CreateFromMemMap(MemMap* mem_map, uintptr_t cover_begin,
133                                              size_t num_bits);
134 
135   // Beginning of the memory range that the bitmap covers.
CoverBegin()136   ALWAYS_INLINE uintptr_t CoverBegin() const {
137     return cover_begin_;
138   }
139 
140   // End of the memory range that the bitmap covers.
CoverEnd()141   ALWAYS_INLINE uintptr_t CoverEnd() const {
142     return cover_end_;
143   }
144 
145   // Return the address associated with a bit index.
AddrFromBitIndex(size_t bit_index)146   ALWAYS_INLINE uintptr_t AddrFromBitIndex(size_t bit_index) const {
147     const uintptr_t addr = CoverBegin() + bit_index * kAlignment;
148     DCHECK_EQ(BitIndexFromAddr(addr), bit_index);
149     return addr;
150   }
151 
152   // Return the bit index associated with an address .
BitIndexFromAddr(uintptr_t addr)153   ALWAYS_INLINE uintptr_t BitIndexFromAddr(uintptr_t addr) const {
154     DCHECK(HasAddress(addr)) << CoverBegin() << " <= " <<  addr << " < " << CoverEnd();
155     return (addr - CoverBegin()) / kAlignment;
156   }
157 
HasAddress(const uintptr_t addr)158   ALWAYS_INLINE bool HasAddress(const uintptr_t addr) const {
159     return cover_begin_ <= addr && addr < cover_end_;
160   }
161 
Set(uintptr_t addr)162   ALWAYS_INLINE bool Set(uintptr_t addr) {
163     return SetBit(BitIndexFromAddr(addr));
164   }
165 
Clear(size_t addr)166   ALWAYS_INLINE bool Clear(size_t addr) {
167     return ClearBit(BitIndexFromAddr(addr));
168   }
169 
Test(size_t addr)170   ALWAYS_INLINE bool Test(size_t addr) const {
171     return TestBit(BitIndexFromAddr(addr));
172   }
173 
174   // Returns true if the object was previously set.
AtomicTestAndSet(size_t addr)175   ALWAYS_INLINE bool AtomicTestAndSet(size_t addr) {
176     return AtomicTestAndSetBit(BitIndexFromAddr(addr));
177   }
178 
179  private:
MemoryRangeBitmap(MemMap * mem_map,uintptr_t begin,size_t num_bits)180   MemoryRangeBitmap(MemMap* mem_map, uintptr_t begin, size_t num_bits)
181      : Bitmap(mem_map, num_bits), cover_begin_(begin), cover_end_(begin + kAlignment * num_bits) {
182   }
183 
184   uintptr_t const cover_begin_;
185   uintptr_t const cover_end_;
186 
187   DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryRangeBitmap);
188 };
189 
190 }  // namespace accounting
191 }  // namespace gc
192 }  // namespace art
193 
194 #endif  // ART_RUNTIME_GC_ACCOUNTING_BITMAP_H_
195