• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef ECMASCRIPT_ECMA_GLOABL_STORAGE_INL_H
16 #define ECMASCRIPT_ECMA_GLOABL_STORAGE_INL_H
17 
18 #include "ecmascript/ecma_global_storage.h"
19 
20 namespace panda::ecmascript {
NodeToNodeList(EcmaGlobalStorage::Node * node)21 inline EcmaGlobalStorage::NodeList *EcmaGlobalStorage::NodeList::NodeToNodeList(
22     EcmaGlobalStorage::Node *node)
23 {
24     uintptr_t ptr = ToUintPtr(node) - node->GetIndex() * sizeof(EcmaGlobalStorage::Node);
25     return reinterpret_cast<NodeList *>(ptr);
26 }
27 
NewNode(JSTaggedType value)28 EcmaGlobalStorage::Node *EcmaGlobalStorage::NodeList::NewNode(JSTaggedType value)
29 {
30     if (IsFull()) {
31         return nullptr;
32     }
33     Node *node = &nodeList_[index_++];
34     node->SetPrev(nullptr);
35     node->SetNext(usedList_);
36     node->SetObject(value);
37     node->SetFree(false);
38 
39     if (usedList_ != nullptr) {
40         usedList_->SetPrev(node);
41     }
42     usedList_ = node;
43     return node;
44 }
45 
FreeNode(EcmaGlobalStorage::Node * node)46 void EcmaGlobalStorage::NodeList::FreeNode(EcmaGlobalStorage::Node *node)
47 {
48     if (node->GetPrev() != nullptr) {
49         node->GetPrev()->SetNext(node->GetNext());
50     }
51     if (node->GetNext() != nullptr) {
52         node->GetNext()->SetPrev(node->GetPrev());
53     }
54     if (node == usedList_) {
55         usedList_ = node->GetNext();
56     }
57     node->SetPrev(nullptr);
58     node->SetNext(freeList_);
59     node->SetObject(JSTaggedValue::Undefined().GetRawData());
60     node->SetFree(true);
61 
62     if (freeList_ != nullptr) {
63         freeList_->SetPrev(node);
64     }
65     freeList_ = node;
66 }
67 
GetFreeNode(JSTaggedType value)68 EcmaGlobalStorage::Node *EcmaGlobalStorage::NodeList::GetFreeNode(JSTaggedType value)
69 {
70     Node *node = freeList_;
71     if (node != nullptr) {
72         freeList_ = node->GetNext();
73 
74         node->SetPrev(nullptr);
75         node->SetNext(usedList_);
76         node->SetObject(value);
77         node->SetFree(false);
78 
79         if (usedList_ != nullptr) {
80             usedList_->SetPrev(node);
81         }
82         usedList_ = node;
83     }
84     return node;
85 }
86 
LinkTo(NodeList * prev)87 void EcmaGlobalStorage::NodeList::LinkTo(NodeList *prev)
88 {
89     next_ = nullptr;
90     prev_ = prev;
91     prev_->next_ = this;
92 }
93 
RemoveList()94 void EcmaGlobalStorage::NodeList::RemoveList()
95 {
96     if (next_ != nullptr) {
97         next_->SetPrev(prev_);
98     }
99     if (prev_ != nullptr) {
100         prev_->SetNext(next_);
101     }
102     if (freeNext_ != nullptr) {
103         freeNext_->SetFreePrev(freePrev_);
104     }
105     if (freePrev_ != nullptr) {
106         freePrev_->SetFreeNext(freeNext_);
107     }
108 }
109 
NewGlobalHandleImplement(NodeList ** storage,NodeList ** freeList,bool isWeak,JSTaggedType value)110 uintptr_t EcmaGlobalStorage::NewGlobalHandleImplement(NodeList **storage, NodeList **freeList,
111                                                       bool isWeak, JSTaggedType value)
112 {
113     if ((*storage)->IsFull() && *freeList == nullptr) {
114         // alloc new block
115         auto block = allocator_->New<NodeList>(isWeak);
116         block->LinkTo(*storage);
117         *storage = block;
118     }
119 
120     // use node in block first
121     Node *node = (*storage)->NewNode(value);
122     if (node != nullptr) {
123         return node->GetObjectAddress();
124     }
125 
126     // use free_list node
127     node = (*freeList)->GetFreeNode(value);
128     ASSERT(node != nullptr);
129     if (!(*freeList)->HasFreeNode()) {
130         auto next = (*freeList)->GetFreeNext();
131         (*freeList)->SetFreeNext(nullptr);
132         (*freeList)->SetFreePrev(nullptr);
133         if (next != nullptr) {
134             next->SetFreePrev(nullptr);
135         }
136         *freeList = next;
137     }
138     return node->GetObjectAddress();
139 }
140 
NewGlobalHandle(JSTaggedType value)141 inline uintptr_t EcmaGlobalStorage::NewGlobalHandle(JSTaggedType value)
142 {
143     return NewGlobalHandleImplement(&lastGlobalNodes_, &freeListNodes_, false, value);
144 }
145 
DisposeGlobalHandle(uintptr_t nodeAddr)146 inline void EcmaGlobalStorage::DisposeGlobalHandle(uintptr_t nodeAddr)
147 {
148     Node *node = reinterpret_cast<Node *>(nodeAddr);
149     if (node->IsFree()) {
150         return;
151     }
152     NodeList *list = NodeList::NodeToNodeList(node);
153     list->FreeNode(node);
154 
155     // If NodeList has no usage node, then delete NodeList
156     NodeList **freeList = nullptr;
157     NodeList **top = nullptr;
158     NodeList **last = nullptr;
159     if (list->IsWeak()) {
160         freeList = &weakFreeListNodes_;
161         top = &topWeakGlobalNodes_;
162         last = &lastWeakGlobalNodes_;
163     } else {
164         freeList = &freeListNodes_;
165         top = &topGlobalNodes_;
166         last = &lastGlobalNodes_;
167     }
168     if (!list->HasUsagedNode() && (*top != *last)) {
169         list->RemoveList();
170         if (*freeList == list) {
171             *freeList = list->GetFreeNext();
172         }
173         if (*top == list) {
174             *top = list->GetNext();
175         }
176         if (*last == list) {
177             *last = list->GetPrev();
178         }
179         allocator_->Delete(list);
180     } else {
181         // Add to freeList
182         if (list != *freeList && list->GetFreeNext() == nullptr && list->GetFreePrev() == nullptr) {
183             list->SetFreeNext(*freeList);
184             if (*freeList != nullptr) {
185                 (*freeList)->SetFreePrev(list);
186             }
187             *freeList = list;
188         }
189     }
190 }
191 
SetWeak(uintptr_t nodeAddr)192 inline uintptr_t EcmaGlobalStorage::SetWeak(uintptr_t nodeAddr)
193 {
194     auto value = reinterpret_cast<Node *>(nodeAddr)->GetObject();
195     DisposeGlobalHandle(nodeAddr);
196     return NewGlobalHandleImplement(&lastWeakGlobalNodes_, &weakFreeListNodes_, true, value);
197 }
198 
ClearWeak(uintptr_t nodeAddr)199 inline uintptr_t EcmaGlobalStorage::ClearWeak(uintptr_t nodeAddr)
200 {
201     auto value = reinterpret_cast<Node *>(nodeAddr)->GetObject();
202     DisposeGlobalHandle(nodeAddr);
203     return NewGlobalHandleImplement(&lastGlobalNodes_, &freeListNodes_, false, value);
204 }
205 
IsWeak(uintptr_t addr)206 inline bool EcmaGlobalStorage::IsWeak(uintptr_t addr) const
207 {
208     Node *node = reinterpret_cast<Node *>(addr);
209     NodeList *list = NodeList::NodeToNodeList(node);
210     return list->IsWeak();
211 }
212 }  // namespace panda::ecmascript
213 #endif  // ECMASCRIPT_ECMA_GLOABL_STORAGE_INL_H
214