1 /**
2 * Copyright (c) 2021-2025 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 ark {
23 template <typename T>
GetNodeAddress(uint32_t index)24 inline 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>
34 // CC-OFFNXT(G.FUD.06) solid logic
NewHandle(T value)35 inline uintptr_t HandleStorage<T>::NewHandle(T value)
36 {
37 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2;
38 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK;
39 if (nodes_.size() <= nid) {
40 auto n = allocator_->New<std::array<T, NODE_BLOCK_SIZE>>();
41 nodes_.push_back(n);
42 }
43 auto node = nodes_[nid];
44 auto loc = &(*node)[offset];
45 *loc = value;
46 lastIndex_++;
47 return reinterpret_cast<uintptr_t>(loc);
48 }
49
50 template <typename T>
FreeExtraNodes(uint32_t nid)51 inline void HandleStorage<T>::FreeExtraNodes(uint32_t nid)
52 {
53 for (size_t i = nid; i < nodes_.size(); ++i) {
54 allocator_->Delete(nodes_[i]);
55 }
56 if (nid < nodes_.size()) {
57 nodes_.erase(nodes_.begin() + nid, nodes_.end());
58 }
59 }
60
61 template <typename T>
FreeHandles(uint32_t beginIdx)62 inline void HandleStorage<T>::FreeHandles(uint32_t beginIdx)
63 {
64 lastIndex_ = beginIdx;
65 #ifndef NDEBUG
66 ZapFreedHandles();
67 #endif
68 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2;
69 // reserve at least one block for perf.
70 nid++;
71 FreeExtraNodes(nid);
72 }
73
74 template <typename T>
ZapFreedHandlesForNode(std::array<T,NODE_BLOCK_SIZE> * node,uint32_t start)75 void HandleStorage<T>::ZapFreedHandlesForNode(std::array<T, NODE_BLOCK_SIZE> *node, uint32_t start)
76 {
77 for (uint32_t j = start; j < NODE_BLOCK_SIZE; ++j) {
78 node->at(j) = reinterpret_cast<T>(static_cast<uint64_t>(0));
79 }
80 }
81
82 template <typename T>
ZapFreedHandles()83 void HandleStorage<T>::ZapFreedHandles()
84 {
85 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2;
86 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK;
87 for (size_t i = nid; i < nodes_.size(); ++i) {
88 auto node = nodes_.at(i);
89 if (i != nid) {
90 ZapFreedHandlesForNode(node);
91 } else {
92 ZapFreedHandlesForNode(node, offset);
93 }
94 }
95 }
96
97 template <>
UpdateHeapObjectForNode(std::array<coretypes::TaggedType,NODE_BLOCK_SIZE> * node,uint32_t size,const GCRootUpdater & gcRootUpdater)98 inline void HandleStorage<coretypes::TaggedType>::UpdateHeapObjectForNode(
99 std::array<coretypes::TaggedType, NODE_BLOCK_SIZE> *node, uint32_t size, const GCRootUpdater &gcRootUpdater)
100 {
101 for (uint32_t j = 0; j < size; ++j) {
102 coretypes::TaggedValue obj(node->at(j));
103 if (!obj.IsHeapObject()) {
104 continue;
105 }
106 ObjectHeader *objH = obj.GetHeapObject();
107 if (gcRootUpdater(&objH)) {
108 (*node)[j] = coretypes::TaggedValue(objH).GetRawData();
109 }
110 }
111 }
112
113 template <>
114 // CC-OFFNXT(G.FUD.06) solid logic
UpdateHeapObject(const GCRootUpdater & gcRootUpdater)115 inline void HandleStorage<coretypes::TaggedType>::UpdateHeapObject(const GCRootUpdater &gcRootUpdater)
116 {
117 if (lastIndex_ == 0) {
118 return;
119 }
120 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2;
121 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK;
122 for (uint32_t i = 0; i <= nid; ++i) {
123 auto node = nodes_.at(i);
124 uint32_t count = (i != nid) ? NODE_BLOCK_SIZE : offset;
125 UpdateHeapObjectForNode(node, count, gcRootUpdater);
126 }
127 }
128
129 template <>
VisitGCRootsForNode(std::array<coretypes::TaggedType,NODE_BLOCK_SIZE> * node,uint32_t size,const ObjectVisitor & cb)130 inline void HandleStorage<coretypes::TaggedType>::VisitGCRootsForNode(
131 std::array<coretypes::TaggedType, NODE_BLOCK_SIZE> *node, uint32_t size, const ObjectVisitor &cb)
132 {
133 for (uint32_t j = 0; j < size; ++j) {
134 coretypes::TaggedValue obj(node->at(j));
135 if (obj.IsHeapObject()) {
136 cb(obj.GetHeapObject());
137 }
138 }
139 }
140
141 template <>
142 // CC-OFFNXT(G.FUD.06) solid logic
VisitGCRoots(const ObjectVisitor & cb)143 inline void HandleStorage<coretypes::TaggedType>::VisitGCRoots([[maybe_unused]] const ObjectVisitor &cb)
144 {
145 if (lastIndex_ == 0) {
146 return;
147 }
148 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2;
149 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK;
150 if (offset == 0) {
151 nid -= 1;
152 offset = NODE_BLOCK_SIZE;
153 }
154 for (uint32_t i = 0; i <= nid; ++i) {
155 auto node = nodes_.at(i);
156 uint32_t count = (i != nid) ? NODE_BLOCK_SIZE : offset;
157 VisitGCRootsForNode(node, count, cb);
158 }
159 }
160
161 template <>
UpdateHeapObjectForNode(std::array<ObjectHeader *,NODE_BLOCK_SIZE> * node,uint32_t size,const GCRootUpdater & gcRootUpdater)162 inline void HandleStorage<ObjectHeader *>::UpdateHeapObjectForNode(std::array<ObjectHeader *, NODE_BLOCK_SIZE> *node,
163 uint32_t size, const GCRootUpdater &gcRootUpdater)
164 {
165 for (uint32_t j = 0; j < size; ++j) {
166 gcRootUpdater(reinterpret_cast<ObjectHeader **>(&(*node)[j]));
167 }
168 }
169
170 template <>
171 // CC-OFFNXT(G.FUD.06) solid logic
UpdateHeapObject(const GCRootUpdater & gcRootUpdater)172 inline void HandleStorage<ObjectHeader *>::UpdateHeapObject(const GCRootUpdater &gcRootUpdater)
173 {
174 if (lastIndex_ == 0) {
175 return;
176 }
177 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2;
178 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK;
179 if (offset == 0) {
180 nid -= 1;
181 offset = NODE_BLOCK_SIZE;
182 }
183 for (uint32_t i = 0; i <= nid; ++i) {
184 auto node = nodes_.at(i);
185 uint32_t count = (i != nid) ? NODE_BLOCK_SIZE : offset;
186 UpdateHeapObjectForNode(node, count, gcRootUpdater);
187 }
188 }
189
190 template <>
VisitGCRootsForNode(std::array<ObjectHeader *,NODE_BLOCK_SIZE> * node,uint32_t size,const ObjectVisitor & cb)191 inline void HandleStorage<ObjectHeader *>::VisitGCRootsForNode(std::array<ObjectHeader *, NODE_BLOCK_SIZE> *node,
192 uint32_t size, const ObjectVisitor &cb)
193 {
194 for (uint32_t j = 0; j < size; ++j) {
195 auto obj = reinterpret_cast<ObjectHeader *>(node->at(j));
196 cb(obj);
197 }
198 }
199
200 template <>
201 // CC-OFFNXT(G.FUD.06) solid logic
VisitGCRoots(const ObjectVisitor & cb)202 inline void HandleStorage<ObjectHeader *>::VisitGCRoots([[maybe_unused]] const ObjectVisitor &cb)
203 {
204 if (lastIndex_ == 0) {
205 return;
206 }
207 uint32_t nid = lastIndex_ >> NODE_BLOCK_SIZE_LOG2;
208 uint32_t offset = lastIndex_ & NODE_BLOCK_SIZE_MASK;
209 for (uint32_t i = 0; i <= nid; ++i) {
210 auto node = nodes_.at(i);
211 uint32_t count = (i != nid) ? NODE_BLOCK_SIZE : offset;
212 VisitGCRootsForNode(node, count, cb);
213 }
214 }
215
216 template class HandleStorage<coretypes::TaggedType>;
217 } // namespace ark
218
219 #endif // PANDA_RUNTIME_HANDLE_STORAGE_INL_H
220