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