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 PANDA_RUNTIME_HANDLE_STORAGE_INL_H_ 17 #define PANDA_RUNTIME_HANDLE_STORAGE_INL_H_ 18 19 #include "runtime/handle_storage.h" 20 #include "runtime/mem/object_helpers.h" 21 22 namespace panda { 23 template <typename T> GetNodeAddress(uint32_t index)24inline uintptr_t HandleStorage<T>::GetNodeAddress(uint32_t index) const 25 { 26 uint32_t id = index >> NODE_BLOCK_SIZE_LOG2; 27 uint32_t offset = index & NODE_BLOCK_SIZE_MASK; 28 auto node = nodes_[id]; 29 auto location = &(*node)[offset]; 30 return reinterpret_cast<uintptr_t>(location); 31 } 32 33 template <typename T> NewHandle(T value)34inline uintptr_t HandleStorage<T>::NewHandle(T value) 35 { 36 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2; 37 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK; 38 if (nodes_.size() <= nid) { 39 auto n = allocator_->New<std::array<T, NODE_BLOCK_SIZE>>(); 40 nodes_.push_back(n); 41 } 42 auto node = nodes_[nid]; 43 // CODECHECK-NOLINTNEXTLINE(C_RULE_ID_REDUNDANT_INIT) 44 auto loc = &(*node)[offset]; 45 *loc = value; 46 lastIndex_++; 47 return reinterpret_cast<uintptr_t>(loc); 48 } 49 50 template <typename T> FreeHandles(uint32_t beginIndex)51inline void HandleStorage<T>::FreeHandles(uint32_t beginIndex) 52 { 53 lastIndex_ = beginIndex; 54 #ifndef NDEBUG 55 ZapFreedHandles(); 56 #endif 57 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2; 58 // reserve at least one block for perf. 59 nid++; 60 for (size_t i = nid; i < nodes_.size(); ++i) { 61 allocator_->Delete(nodes_[i]); 62 } 63 if (nid < nodes_.size()) { 64 nodes_.erase(nodes_.begin() + nid, nodes_.end()); 65 } 66 } 67 68 template <typename T> ZapFreedHandles()69void HandleStorage<T>::ZapFreedHandles() 70 { 71 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2; 72 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK; 73 for (size_t i = nid; i < nodes_.size(); ++i) { 74 auto node = nodes_.at(i); 75 if (i != nid) { 76 node->fill(reinterpret_cast<T>(static_cast<uint64_t>(0))); 77 } else { 78 for (uint32_t j = offset; j < NODE_BLOCK_SIZE; ++j) { 79 node->at(j) = reinterpret_cast<T>(static_cast<uint64_t>(0)); 80 } 81 } 82 } 83 } 84 85 template <> UpdateHeapObject()86inline void HandleStorage<coretypes::TaggedType>::UpdateHeapObject() 87 { 88 if (lastIndex_ == 0) { 89 return; 90 } 91 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2; 92 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK; 93 for (uint32_t i = 0; i <= nid; ++i) { 94 auto node = nodes_.at(i); 95 uint32_t count = (i != nid) ? NODE_BLOCK_SIZE : offset; 96 for (uint32_t j = 0; j < count; ++j) { 97 coretypes::TaggedValue obj(node->at(j)); 98 if (obj.IsHeapObject() && obj.GetHeapObject()->IsForwarded()) { 99 (*node)[j] = coretypes::TaggedValue(panda::mem::GetForwardAddress(obj.GetHeapObject())).GetRawData(); 100 } 101 } 102 } 103 } 104 105 template <> VisitGCRoots(const ObjectVisitor & cb)106inline void HandleStorage<coretypes::TaggedType>::VisitGCRoots([[maybe_unused]] const ObjectVisitor &cb) 107 { 108 if (lastIndex_ == 0) { 109 return; 110 } 111 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2; 112 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK; 113 if (offset == 0) { 114 nid -= 1; 115 offset = NODE_BLOCK_SIZE; 116 } 117 for (uint32_t i = 0; i <= nid; ++i) { 118 auto node = nodes_.at(i); 119 uint32_t count = (i != nid) ? NODE_BLOCK_SIZE : offset; 120 for (uint32_t j = 0; j < count; ++j) { 121 coretypes::TaggedValue obj(node->at(j)); 122 if (obj.IsHeapObject()) { 123 cb(obj.GetHeapObject()); 124 } 125 } 126 } 127 } 128 129 template <> UpdateHeapObject()130inline void HandleStorage<ObjectHeader *>::UpdateHeapObject() 131 { 132 if (lastIndex_ == 0) { 133 return; 134 } 135 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2; 136 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK; 137 if (offset == 0) { 138 nid -= 1; 139 offset = NODE_BLOCK_SIZE; 140 } 141 for (uint32_t i = 0; i <= nid; ++i) { 142 auto node = nodes_.at(i); 143 uint32_t count = (i != nid) ? NODE_BLOCK_SIZE : offset; 144 for (uint32_t j = 0; j < count; ++j) { 145 auto *obj = reinterpret_cast<ObjectHeader *>(node->at(j)); 146 if (obj->IsForwarded()) { 147 (*node)[j] = ::panda::mem::GetForwardAddress(obj); 148 } 149 } 150 } 151 } 152 153 template <> VisitGCRoots(const ObjectVisitor & cb)154inline void HandleStorage<ObjectHeader *>::VisitGCRoots([[maybe_unused]] const ObjectVisitor &cb) 155 { 156 if (lastIndex_ == 0) { 157 return; 158 } 159 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2; 160 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK; 161 for (uint32_t i = 0; i <= nid; ++i) { 162 auto node = nodes_.at(i); 163 uint32_t count = (i != nid) ? NODE_BLOCK_SIZE : offset; 164 for (uint32_t j = 0; j < count; ++j) { 165 auto obj = reinterpret_cast<ObjectHeader *>(node->at(j)); 166 cb(obj); 167 } 168 } 169 } 170 171 template class HandleStorage<coretypes::TaggedType>; 172 173 } // namespace panda 174 175 #endif // PANDA_RUNTIME_HANDLE_STORAGE_INL_H_ 176