1 /** 2 * Copyright (c) 2021-2022 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 #ifndef PANDA_RUNTIME_MEM_REF_BLOCK_H 16 #define PANDA_RUNTIME_MEM_REF_BLOCK_H 17 18 #include <cstddef> 19 #include <limits> 20 21 #include "include/object_header.h" 22 #include <libpandabase/mem/object_pointer.h> 23 #include "runtime/mem/refstorage/reference.h" 24 #include "runtime/mem/object_helpers.h" 25 #include "runtime/mem/gc/gc_root.h" 26 27 namespace panda::mem::test { 28 class ReferenceStorageTest; 29 } // namespace panda::mem::test 30 31 namespace panda::mem { 32 33 class RefBlock { 34 using SlotBitMap = uint64_t; 35 36 class Iterator { 37 RefBlock *ref_block_; 38 39 public: Iterator(RefBlock * ref_block)40 explicit Iterator(RefBlock *ref_block) : ref_block_(ref_block) {} 41 42 ~Iterator() = default; 43 44 DEFAULT_COPY_SEMANTIC(Iterator); 45 DEFAULT_MOVE_SEMANTIC(Iterator); 46 47 RefBlock *operator*() const 48 { 49 return ref_block_; 50 } 51 52 Iterator &operator++() 53 { 54 ref_block_ = ref_block_->GetPrev(); 55 return *this; 56 } 57 58 const Iterator operator++(int) // NOLINT(readability-const-return-type) 59 { 60 Iterator tmp = *this; 61 ++(*this); 62 return tmp; 63 } 64 65 friend bool operator==(const Iterator &a, const Iterator &b) 66 { 67 return a.ref_block_ == b.ref_block_; 68 } 69 70 friend bool operator!=(const Iterator &a, const Iterator &b) 71 { 72 return a.ref_block_ != b.ref_block_; 73 } 74 }; 75 76 static constexpr unsigned int REFS_IN_BLOCK = 60; 77 static constexpr SlotBitMap START_VALUE = std::numeric_limits<SlotBitMap>::max(); 78 static constexpr SlotBitMap FINAL_VALUE = 79 std::numeric_limits<SlotBitMap>::max() & (~((static_cast<SlotBitMap>(1U) << REFS_IN_BLOCK) - 1U)); 80 81 // should be first field in the class 82 ObjectPointer<ObjectHeader> refs_[REFS_IN_BLOCK]; // NOLINT(modernize-avoid-c-arrays) 83 84 // slots in the array. slot is free - bit=1, slot is busy - bit=0 85 SlotBitMap slots_ {START_VALUE}; 86 87 RefBlock *prev_block_ {nullptr}; 88 89 public: 90 explicit RefBlock(RefBlock *prev); 91 RefBlock()92 RefBlock() : RefBlock(nullptr) {} 93 Reset()94 void Reset() 95 { 96 Reset(nullptr); 97 } 98 99 void Reset(RefBlock *prev); 100 IsFull()101 bool IsFull() const 102 { 103 return slots_ == FINAL_VALUE; 104 } 105 IsEmpty()106 bool IsEmpty() const 107 { 108 return slots_ == START_VALUE; 109 } 110 111 Reference *AddRef(const ObjectHeader *object, Reference::ObjectType type); 112 113 void Remove(const Reference *ref); 114 GetPrev()115 RefBlock *GetPrev() const 116 { 117 return prev_block_; 118 } 119 120 void VisitObjects(const GCRootVisitor &gc_root_visitor, mem::RootType rootType); 121 122 void UpdateMovedRefs(); 123 124 // used only for dumping and tests 125 PandaVector<Reference *> GetAllReferencesInFrame(); 126 begin()127 Iterator begin() // NOLINT(readability-identifier-naming) 128 { 129 return Iterator(this); 130 } 131 end()132 Iterator end() // NOLINT(readability-identifier-naming) 133 { 134 return Iterator(nullptr); 135 } 136 137 ~RefBlock() = default; 138 139 DEFAULT_COPY_SEMANTIC(RefBlock); 140 DEFAULT_MOVE_SEMANTIC(RefBlock); 141 142 private: 143 uint8_t GetFreeIndex(); 144 145 void Set(uint8_t index, const ObjectHeader *object); 146 147 bool IsFreeIndex(uint8_t index); 148 149 bool IsBusyIndex(uint8_t index); 150 151 void PrintBlock(); 152 153 // test purpose only, don't use in production 154 DumpFrame()155 void DumpFrame() 156 { 157 std::cout << "Dump chain start --------------"; 158 for (auto block : *this) { 159 std::cout << std::endl << "block: " << std::hex << &block << std::endl; 160 block->PrintBlock(); 161 } 162 std::cout << std::endl << "Dump chain finish --------------" << std::endl; 163 } 164 DumpBlock()165 void DumpBlock() 166 { 167 std::cout << "Dump block start --------------" << std::endl; 168 std::cout << std::endl << "block: " << std::hex << this << std::endl; 169 PrintBlock(); 170 std::cout << std::endl << "Dump block finish --------------" << std::endl; 171 } 172 friend class panda::mem::test::ReferenceStorageTest; 173 friend class panda::mem::ReferenceStorage; 174 }; 175 176 } // namespace panda::mem 177 178 #endif // PANDA_RUNTIME_MEM_REF_BLOCK_H 179