• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2023-2024 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_PLUGINS_ETS_RUNTIME_INTEROP_JS_ITEM_POOL_H_
17 #define PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_ITEM_POOL_H_
18 
19 #include "libpandabase/macros.h"
20 #include "libpandabase/utils/math_helpers.h"
21 
22 namespace ark::ets::interop::js::ets_proxy {
23 
24 namespace testing {
25 class ItemsPoolTest;
26 }  // namespace testing
27 
28 template <typename Item, uint32_t NR_INDEX_BITS>
29 class ItemsPool {
30     union PaddedItem {
31         Item item;
32         PaddedItem *next;
33         std::array<uint8_t, helpers::math::GetPowerOfTwoValue32(sizeof(Item))> aligned;
34 
PaddedItem()35         PaddedItem()
36         {
37             new (&item) Item();
38         }
~PaddedItem()39         ~PaddedItem()
40         {
41             item.~Item();
42         }
43         NO_COPY_SEMANTIC(PaddedItem);
44         NO_MOVE_SEMANTIC(PaddedItem);
45     };
46 
47     static constexpr size_t MAX_INDEX = 1U << NR_INDEX_BITS;
48     static constexpr size_t PADDED_ITEM_SIZE = sizeof(PaddedItem);
49 
GetPaddedItem(Item * item)50     static PaddedItem *GetPaddedItem(Item *item)
51     {
52         ASSERT(uintptr_t(item) % PADDED_ITEM_SIZE == 0);
53         return reinterpret_cast<PaddedItem *>(item);
54     }
55 
56 public:
57     static constexpr size_t MAX_POOL_SIZE = (1U << NR_INDEX_BITS) * PADDED_ITEM_SIZE;
58 
ItemsPool(void * data,size_t size)59     ItemsPool(void *data, size_t size)
60         : data_(reinterpret_cast<PaddedItem *>(data)),
61           dataEnd_(reinterpret_cast<PaddedItem *>(uintptr_t(data_) + size)),
62           currentPos_(reinterpret_cast<PaddedItem *>(data))
63     {
64         ASSERT(data != nullptr);
65         ASSERT(size % PADDED_ITEM_SIZE == 0);
66     }
67     ~ItemsPool() = default;
68 
GetNextAlloc()69     Item *GetNextAlloc() const
70     {
71         if (freeList_ != nullptr) {
72             return &freeList_->item;
73         }
74         return (currentPos_ < dataEnd_) ? &currentPos_->item : nullptr;
75     }
76 
AllocItem()77     Item *AllocItem()
78     {
79         if (freeList_ != nullptr) {
80             PaddedItem *newItem = freeList_;
81             freeList_ = freeList_->next;
82             return &(new (newItem) PaddedItem())->item;
83         }
84 
85         if (UNLIKELY(currentPos_ >= dataEnd_)) {
86             // Out of memory
87             return nullptr;
88         }
89 
90         PaddedItem *newItem = currentPos_;
91         ++currentPos_;  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
92         return &(new (newItem) PaddedItem())->item;
93     }
94 
FreeItem(Item * item)95     void FreeItem(Item *item)
96     {
97         PaddedItem *paddedItem = GetPaddedItem(item);
98         paddedItem->~PaddedItem();
99         paddedItem->next = freeList_;
100         freeList_ = paddedItem;
101     }
102 
103     //  This method only checks the validity of the item in the allocated interval
104     //  This method does not check whether the item has been allocated or not
IsValidItem(const Item * item)105     bool IsValidItem(const Item *item) const
106     {
107         if (UNLIKELY(!IsAligned<alignof(Item)>(uintptr_t(item)))) {
108             return false;
109         }
110         auto addr = uintptr_t(item);
111         return uintptr_t(data_) <= addr && addr < uintptr_t(dataEnd_);
112     }
113 
GetIndexByItem(Item * item)114     inline uint32_t GetIndexByItem(Item *item)
115     {
116         ASSERT(IsValidItem(item));
117         ASSERT(uintptr_t(item) % PADDED_ITEM_SIZE == 0);
118 
119         PaddedItem *paddedItem = GetPaddedItem(item);
120         return paddedItem - data_;
121     }
122 
GetItemByIndex(uint32_t idx)123     inline Item *GetItemByIndex(uint32_t idx)
124     {
125         ASSERT(idx < MAX_INDEX);
126         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic,cppcoreguidelines-pro-type-union-access)
127         return &data_[idx].item;
128     }
129 
130     NO_COPY_SEMANTIC(ItemsPool);
131     NO_MOVE_SEMANTIC(ItemsPool);
132 
133 private:
134     PaddedItem *const data_ {};
135     PaddedItem *const dataEnd_ {};
136     PaddedItem *currentPos_ {};
137     PaddedItem *freeList_ {};
138 
139     friend testing::ItemsPoolTest;
140 };
141 
142 }  // namespace ark::ets::interop::js::ets_proxy
143 
144 #endif  // !PANDA_PLUGINS_ETS_RUNTIME_INTEROP_JS_ITEM_POOL_H_
145