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_ECMA_GLOABL_STORAGE_H 17 #define ECMASCRIPT_ECMA_GLOABL_STORAGE_H 18 19 #include "ecmascript/js_tagged_value.h" 20 21 #include "ecmascript/mem/c_containers.h" 22 #include "ecmascript/mem/native_area_allocator.h" 23 24 namespace panda::ecmascript { 25 class EcmaGlobalStorage { 26 public: 27 static const int32_t GLOBAL_BLOCK_SIZE = 256; 28 EcmaGlobalStorage(NativeAreaAllocator * allocator)29 explicit EcmaGlobalStorage(NativeAreaAllocator *allocator) : allocator_(allocator) 30 { 31 ASSERT(allocator != nullptr); 32 topGlobalNodes_ = lastGlobalNodes_ = allocator_->New<NodeList>(false); 33 topWeakGlobalNodes_ = lastWeakGlobalNodes_ = allocator_->New<NodeList>(true); 34 } 35 ~EcmaGlobalStorage()36 ~EcmaGlobalStorage() 37 { 38 NodeList *next = topGlobalNodes_; 39 NodeList *current = nullptr; 40 while (next != nullptr) { 41 current = next; 42 next = current->GetNext(); 43 allocator_->Delete(current); 44 } 45 46 next = topWeakGlobalNodes_; 47 while (next != nullptr) { 48 current = next; 49 next = current->GetNext(); 50 allocator_->Delete(current); 51 } 52 } 53 54 class Node { 55 public: GetObject()56 JSTaggedType GetObject() const 57 { 58 return obj_; 59 } 60 SetObject(JSTaggedType obj)61 void SetObject(JSTaggedType obj) 62 { 63 obj_ = obj; 64 } 65 GetNext()66 Node *GetNext() const 67 { 68 return next_; 69 } 70 SetNext(Node * node)71 void SetNext(Node *node) 72 { 73 next_ = node; 74 } 75 GetPrev()76 Node *GetPrev() const 77 { 78 return prev_; 79 } 80 SetPrev(Node * node)81 void SetPrev(Node *node) 82 { 83 prev_ = node; 84 } 85 GetIndex()86 int32_t GetIndex() 87 { 88 return index_; 89 } 90 SetIndex(int32_t index)91 void SetIndex(int32_t index) 92 { 93 index_ = index; 94 } 95 SetFree(bool free)96 void SetFree(bool free) 97 { 98 isFree_ = free; 99 } 100 IsFree()101 bool IsFree() const 102 { 103 return isFree_; 104 } 105 GetObjectAddress()106 uintptr_t GetObjectAddress() const 107 { 108 return reinterpret_cast<uintptr_t>(&obj_); 109 } 110 111 private: 112 JSTaggedType obj_; 113 Node *next_ {nullptr}; 114 Node *prev_ {nullptr}; 115 int32_t index_ {-1}; 116 bool isFree_ {false}; 117 }; 118 119 class NodeList { 120 public: NodeList(bool isWeak)121 NodeList(bool isWeak) : isWeak_(isWeak) 122 { 123 for (int i = 0; i < GLOBAL_BLOCK_SIZE; i++) { 124 nodeList_[i].SetIndex(i); 125 } 126 } 127 ~NodeList() = default; 128 129 inline static NodeList *NodeToNodeList(Node *node); 130 131 inline Node *NewNode(JSTaggedType value); 132 inline Node *GetFreeNode(JSTaggedType value); 133 inline void FreeNode(Node *node); 134 135 inline void LinkTo(NodeList *prev); 136 inline void RemoveList(); 137 IsFull()138 inline bool IsFull() 139 { 140 return index_ >= GLOBAL_BLOCK_SIZE; 141 } 142 IsWeak()143 inline bool IsWeak() 144 { 145 return isWeak_; 146 } 147 HasFreeNode()148 inline bool HasFreeNode() 149 { 150 return freeList_ != nullptr; 151 } 152 HasUsagedNode()153 inline bool HasUsagedNode() 154 { 155 return !IsFull() || usedList_ != nullptr; 156 } 157 SetNext(NodeList * next)158 inline void SetNext(NodeList *next) 159 { 160 next_ = next; 161 } GetNext()162 inline NodeList *GetNext() const 163 { 164 return next_; 165 } 166 SetPrev(NodeList * prev)167 inline void SetPrev(NodeList *prev) 168 { 169 prev_ = prev; 170 } GetPrev()171 inline NodeList *GetPrev() const 172 { 173 return prev_; 174 } 175 SetFreeNext(NodeList * next)176 inline void SetFreeNext(NodeList *next) 177 { 178 freeNext_ = next; 179 } GetFreeNext()180 inline NodeList *GetFreeNext() const 181 { 182 return freeNext_; 183 } 184 SetFreePrev(NodeList * prev)185 inline void SetFreePrev(NodeList *prev) 186 { 187 freePrev_ = prev; 188 } GetFreePrev()189 inline NodeList *GetFreePrev() const 190 { 191 return freePrev_; 192 } 193 194 template<class Callback> IterateUsageGlobal(Callback callback)195 inline void IterateUsageGlobal(Callback callback) 196 { 197 Node *next = usedList_; 198 Node *current = nullptr; 199 while (next != nullptr) { 200 current = next; 201 next = current->GetNext(); 202 ASSERT(current != next); 203 callback(current); 204 } 205 } 206 207 private: 208 Node nodeList_[GLOBAL_BLOCK_SIZE]; // all 209 Node *freeList_ {nullptr}; // dispose node 210 Node *usedList_ {nullptr}; // usage node 211 int32_t index_ {0}; 212 bool isWeak_ {false}; 213 NodeList *next_ {nullptr}; 214 NodeList *prev_ {nullptr}; 215 NodeList *freeNext_ {nullptr}; 216 NodeList *freePrev_ {nullptr}; 217 }; 218 219 inline uintptr_t NewGlobalHandle(JSTaggedType value); 220 inline void DisposeGlobalHandle(uintptr_t addr); 221 inline uintptr_t SetWeak(uintptr_t addr); 222 inline uintptr_t ClearWeak(uintptr_t addr); 223 inline bool IsWeak(uintptr_t addr) const; 224 225 template<class Callback> IterateUsageGlobal(Callback callback)226 void IterateUsageGlobal(Callback callback) 227 { 228 NodeList *next = topGlobalNodes_; 229 NodeList *current = nullptr; 230 while (next != nullptr) { 231 current = next; 232 next = current->GetNext(); 233 ASSERT(current != next); 234 current->IterateUsageGlobal(callback); 235 } 236 } 237 238 template<class Callback> IterateWeakUsageGlobal(Callback callback)239 void IterateWeakUsageGlobal(Callback callback) 240 { 241 NodeList *next = topWeakGlobalNodes_; 242 NodeList *current = nullptr; 243 while (next != nullptr) { 244 current = next; 245 next = current->GetNext(); 246 ASSERT(current != next); 247 current->IterateUsageGlobal(callback); 248 } 249 } 250 251 private: 252 NO_COPY_SEMANTIC(EcmaGlobalStorage); 253 NO_MOVE_SEMANTIC(EcmaGlobalStorage); 254 255 inline uintptr_t NewGlobalHandleImplement(NodeList **storage, NodeList **freeList, bool isWeak, JSTaggedType value); 256 257 NativeAreaAllocator *allocator_ {nullptr}; 258 NodeList *topGlobalNodes_ {nullptr}; 259 NodeList *lastGlobalNodes_ {nullptr}; 260 NodeList *freeListNodes_ {nullptr}; 261 262 NodeList *topWeakGlobalNodes_ {nullptr}; 263 NodeList *lastWeakGlobalNodes_ {nullptr}; 264 NodeList *weakFreeListNodes_ {nullptr}; 265 }; 266 } // namespace panda::ecmascript 267 #endif // ECMASCRIPT_ECMA_GLOABL_STORAGE_H 268