Home | History | Annotate | Download | only in accounting
      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.
     48   static ALWAYS_INLINE constexpr size_t BitIndexToWordIndex(uintptr_t offset) {
     49     return offset / kBitsPerBitmapWord;
     50   }
     51 
     52   template<typename T>
     53   static ALWAYS_INLINE constexpr T WordIndexToBitIndex(T word_index) {
     54     return static_cast<T>(word_index * kBitsPerBitmapWord);
     55   }
     56 
     57   static ALWAYS_INLINE constexpr uintptr_t BitIndexToMask(uintptr_t bit_index) {
     58     return static_cast<uintptr_t>(1) << (bit_index % kBitsPerBitmapWord);
     59   }
     60 
     61   ALWAYS_INLINE bool SetBit(size_t bit_index) {
     62     return ModifyBit<true>(bit_index);
     63   }
     64 
     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.
     85   uintptr_t* Begin() {
     86     return bitmap_begin_;
     87   }
     88 
     89   // Size of our bitmap in bits.
     90   size_t BitmapSize() const {
     91     return bitmap_size_;
     92   }
     93 
     94   // Check that a bit index is valid with a DCHECK.
     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.
    136   ALWAYS_INLINE uintptr_t CoverBegin() const {
    137     return cover_begin_;
    138   }
    139 
    140   // End of the memory range that the bitmap covers.
    141   ALWAYS_INLINE uintptr_t CoverEnd() const {
    142     return cover_end_;
    143   }
    144 
    145   // Return the address associated with a 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 .
    153   ALWAYS_INLINE uintptr_t BitIndexFromAddr(uintptr_t addr) const {
    154     DCHECK(HasAddress(addr)) << CoverBegin() << " <= " <<  addr << " < " << CoverEnd();
    155     return (addr - CoverBegin()) / kAlignment;
    156   }
    157 
    158   ALWAYS_INLINE bool HasAddress(const uintptr_t addr) const {
    159     return cover_begin_ <= addr && addr < cover_end_;
    160   }
    161 
    162   ALWAYS_INLINE bool Set(uintptr_t addr) {
    163     return SetBit(BitIndexFromAddr(addr));
    164   }
    165 
    166   ALWAYS_INLINE bool Clear(size_t addr) {
    167     return ClearBit(BitIndexFromAddr(addr));
    168   }
    169 
    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.
    175   ALWAYS_INLINE bool AtomicTestAndSet(size_t addr) {
    176     return AtomicTestAndSetBit(BitIndexFromAddr(addr));
    177   }
    178 
    179  private:
    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