1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_MEM_REMEMBERED_SET_H 17 #define ECMASCRIPT_MEM_REMEMBERED_SET_H 18 19 #include "ecmascript/mem/mem.h" 20 #include "mem/gc/bitmap.h" 21 22 namespace panda::ecmascript { 23 enum class SlotStatus : bool { 24 KEEP_SLOT, 25 CLEAR_SLOT, 26 }; 27 28 class RememberedSet : public mem::Bitmap { 29 public: 30 using RememberedWordType = uintptr_t; 31 static const size_t BYTESPERCHUNK = static_cast<size_t>(MemAlignment::MEM_ALIGN_OBJECT); 32 RememberedSet(uintptr_t begin_addr,size_t range_size,uintptr_t bitset_addr)33 RememberedSet(uintptr_t begin_addr, size_t range_size, uintptr_t bitset_addr) 34 : mem::Bitmap(reinterpret_cast<mem::Bitmap::BitmapWordType *>(bitset_addr), range_size / BYTESPERCHUNK), 35 beginAddr_(begin_addr) 36 { 37 } 38 ~RememberedSet() = default; 39 NO_COPY_SEMANTIC(RememberedSet); 40 NO_MOVE_SEMANTIC(RememberedSet); 41 Insert(uintptr_t address)42 void Insert(uintptr_t address) 43 { 44 SetBit(AddrToBitOffset(address)); 45 } 46 AtomicInsert(uintptr_t address)47 void AtomicInsert(uintptr_t address) 48 { 49 AtomicTestAndSetBit(AddrToBitOffset(address)); 50 } 51 52 template<typename VisitorType> IterateOverSetBits(VisitorType visitor)53 void IterateOverSetBits(VisitorType visitor) 54 { 55 IterateOverSetBitsInRange(0, Size(), visitor); 56 } 57 58 template<typename MemVisitor> IterateOverMarkedChunks(MemVisitor visitor)59 void IterateOverMarkedChunks(MemVisitor visitor) 60 { 61 IterateOverSetBits( 62 [&visitor, this](size_t bit_offset) -> bool { return visitor(BitOffsetToAddr(bit_offset)); }); 63 } 64 Clear(uintptr_t address)65 void Clear(uintptr_t address) 66 { 67 ClearBit(AddrToBitOffset(address)); 68 } 69 ClearRange(uintptr_t begin,uintptr_t end)70 void ClearRange(uintptr_t begin, uintptr_t end) 71 { 72 ClearBitsInRange(AddrToBitOffset(begin), AddrToBitOffset(end)); 73 } 74 GetSizeInByte(size_t range_size)75 static size_t GetSizeInByte(size_t range_size) 76 { 77 return (range_size >> mem::Bitmap::LOG_BITSPERWORD) / BYTESPERCHUNK * sizeof(mem::Bitmap::BitmapWordType); 78 } 79 80 static constexpr uint32_t GetBeginAddrOffset(bool is32Bit = false) 81 { 82 return is32Bit ? BITMAP_MEMBER_SIZE_32 : BITMAP_MEMBER_SIZE_64; 83 } 84 CheckLayout()85 static constexpr bool CheckLayout() 86 { 87 #ifdef PANDA_TARGET_32 88 static_assert(GetBeginAddrOffset(true) == MEMBER_OFFSET(RememberedSet, beginAddr_)); 89 #else 90 static_assert(GetBeginAddrOffset(false) == MEMBER_OFFSET(RememberedSet, beginAddr_)); 91 #endif 92 return true; 93 } 94 95 private: BitOffsetToAddr(size_t bit_offset)96 void *BitOffsetToAddr(size_t bit_offset) const 97 { 98 return ToVoidPtr(beginAddr_ + bit_offset * BYTESPERCHUNK); 99 } 100 AddrToBitOffset(uintptr_t addr)101 size_t AddrToBitOffset(uintptr_t addr) const 102 { 103 return (addr - beginAddr_) / BYTESPERCHUNK; 104 } 105 // BitMap class consist members: bitmap_ and bitsize_ 106 static constexpr size_t BITMAP_MEMBER_SIZE_64 = sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t); 107 static constexpr size_t BITMAP_MEMBER_SIZE_32 = sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t); 108 uintptr_t beginAddr_; 109 }; 110 static_assert(RememberedSet::CheckLayout()); 111 } // namespace panda::ecmascript 112 113 #endif // ECMASCRIPT_MEM_REMEMBERED_SET_H 114