art的bitmap使用

bitmap的原理

art的bitmap使用_第1张图片

bitmap是一块内存,利用其中的每一位去标记对应的内存是否被使用,1为被使用,0位没有使用。

 

SpaceBitmap

art中使用SpacBitmap 对heap进行标记,我们看下spaceBitmap的重要逻辑

a. Creat函数初始化

-----------Create-------------------------------------------------

SpaceBitmap* SpaceBitmap::Create(const std::string& name, uint8_t* heap_begin, size_t heap_capacity) {

    //bitmap_size(标记heap_capacity大小需要的 字节数)

    const size_t bitmap_size = ComputeBitmapSize(heap_capacity);

    |____________________ComputeBitmapSize ________________________________________________________________________________________________

    //理论上我们1个bit标记一个kAlignment大小字节的内存,而我们不能直接创建对象操作bit,这里利用intptr_t 和 uintptr_t数据类型。

    //标记的时候我们一般先找到内存对应bitmap所在的uintptr_t 对象位置,然后在针对uintptr_t对象进行按位操作。

    //这里这份size计算如下:capacity 代表标记的heap大小,单位是字节

    size_t SpaceBitmap::ComputeBitmapSize(uint64_t capacity) {

        // kBitsPerIntPtrT代表一个intptr_t 数据类型占用多少位,32位平台是32,64位平台是64,kAlignment  kAlignment是bit标记的内存大小,

        //一般标记object 是8byte,而标记page是4byte。 假设64位平台标记object,一个intptr_t 对象可以标记8*64=512字节

        const uint64_t kBytesCoveredPerWord = kAlignment * kBitsPerIntPtrT; 

        //这个主要是对capacity 补位到kBytesCoveredPerWord 的整数倍,然后再属于intptr_t大小得到需要的bitmap大小。

        return  (RoundUp(capacity, kBytesCoveredPerWord) / kBytesCoveredPerWord) * sizeof(intptr_t);

    }

    |_______________________________________________________________________________________________________________________________________________

    //通过MapAnonymous创建一块内存给SpaceBitmap进行标记

    MemMap mem_map = MemMap::MapAnonymous(name.c_str(),bitmap_size,PROT_READ | PROT_WRITE,/*low_4gb=*/ false,&error_msg);

    return CreateFromMemMap(name, std::move(mem_map), heap_begin, heap_capacity);

}

template

SpaceBitmap* SpaceBitmap::CreateFromMemMap(const std::string& name, MemMap&& mem_map, uint8_t* heap_begin, size_t heap_capacity) {

    uintptr_t* bitmap_begin = reinterpret_cast(mem_map.Begin());

    const size_t bitmap_size = ComputeBitmapSize(heap_capacity);

    //我们根据创建的mem_map,调用SpaceBitmap构造函数,初始化

    //----bitmap_begin      SpaceBitmap内存基地址

    //----bitmap_size         SpaceBitmap的内存大小

    //----heap_begin          标记的heap的内存基地址

    //----heap_capacity      标记的heap的大小

    return new SpaceBitmap(name, std::move(mem_map), bitmap_begin, bitmap_size, heap_begin, heap_capacity);

}

 

  

b.标记函数set  和清除函数 ,传入对象的地址

bool Set(const mirror::Object* obj) ALWAYS_INLINE {

    return Modify<true>(obj);

}  

bool Clear(const mirror::Object* obj) ALWAYS_INLINE {

    return Modify<false>(obj);

}

template

template

inline bool SpaceBitmap::Modify(const mirror::Object* obj) {

    //将obj的地址转换为uintptr_t 对象

    uintptr_t addr = reinterpret_cast(obj);

    //计算obj相对于heap基地址的偏移

    const uintptr_t offset = addr - heap_begin_;

    //根据偏移大小计算标记位在spaceBitmap中uintptr_t 对象的位置

    const size_t index = OffsetToIndex(offset);

    //根据偏移大小计算标记bit位在uintptr_t 对象中的位置,也就是mask 对象中对应的bit位为1,其他bit位为0

    const uintptr_t mask = OffsetToMask(offset);

    //根据index 取出对应标记uintptr_t对象atomic_entry

    Atomic* atomic_entry = &bitmap_begin_[index];

    //读出atomic_entry 的值

    uintptr_t old_word = atomic_entry->load(std::memory_order_relaxed);

    if (kSetBit) { //set是true,clear是false

        if ((old_word & mask) == 0) { //没有被标记这个判断为0,则进行标记

            atomic_entry->store(old_word | mask, std::memory_order_relaxed);

        }

    else {

        清除标记,对应位置1=0

        atomic_entry->store(old_word & ~mask, std::memory_order_relaxed);

    }

    return (old_word & mask) != 0;

}

 

 

c.遍历函数Walk

template

template

void SpaceBitmap::Walk(Visitor&& visitor) {

    //计算目前使用的heap对应的bitmap大小

    uintptr_t end = OffsetToIndex(HeapLimit() - heap_begin_ - 1);

           

    Atomic* bitmap_begin = bitmap_begin_;

    //遍历bitmap的uintptr_t 对象

    for (uintptr_t i = 0; i <= end; ++i) {

        //取出uintptr_t 值

        uintptr_t w = bitmap_begin[i].load(std::memory_order_relaxed);

        if (w != 0) { //对应的uintptr_t 有bit位为1,也就是有对应的标记对象

            uintptr_t ptr_base = IndexToOffset(i) + heap_begin_;//找到uintptr_t 标记对象的偏移地址,然后+base得到实际地址

            do {

                //找到uintptr_t 不为0的第一个位置,低位开始

                const size_t shift = CTZ(w);

                //拿到shift 标记的内存的地址,并转化为object对象

                mirror::Object* obj = reinterpret_cast(ptr_base + shift * kAlignment);

                //回调visitor函数

                visitor(obj);

                w ^= (static_cast(1)) << shift;//把对应位置0,好继续找下一个非0位

            while (w != 0);

        }

    }

}


HeapBitMap

它是一个辅助类,里面存了两个重要的对象

// Bitmaps covering continuous spaces.
std::vector>continuous_space_bitmaps_;

// Sets covering discontinuous spaces.
std::vector>large_object_bitmaps_;

你可能感兴趣的:(art的bitmap使用)