• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 #include "ecmascript/tagged_tree.h"
17 
18 #include "ecmascript/js_object-inl.h"
19 #include "ecmascript/object_factory.h"
20 
21 namespace panda::ecmascript {
22 template<typename Derived>
Create(const JSThread * thread,int numberOfElements)23 JSHandle<Derived> TaggedTree<Derived>::Create(const JSThread *thread, int numberOfElements)
24 {
25     ASSERT_PRINT(numberOfElements > 0, "size must be a non-negative integer");
26     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
27     auto capacity = numberOfElements > MIN_CAPACITY ? static_cast<uint32_t>(numberOfElements) : MIN_CAPACITY;
28     int length = ELEMENTS_START_INDEX + capacity * (Derived::ENTRY_SIZE);
29 
30     auto tree = JSHandle<Derived>::Cast(factory->NewTaggedArray(length));
31     tree->SetNumberOfElements(thread, 0);
32     tree->SetNumberOfDeletedElements(thread, 0);
33     tree->SetRootEntries(thread, -1);
34     tree->SetCompare(thread, JSTaggedValue::Hole());
35     tree->SetCapacity(thread, capacity);
36     return tree;
37 }
38 
39 template<typename Derived>
InsertRebalance(const JSThread * thread,int index)40 void TaggedTree<Derived>::InsertRebalance(const JSThread *thread, int index)
41 {
42     while (IsValidIndex(index) && GetColor(GetParent(index)) == TreeColor::RED) {
43         if (IsLeft(GetParent(index))) {
44             int bro = GetLeftBrother(GetParent(index));
45             if (GetColor(bro)) {
46                 SetColor(thread, GetParent(index), TreeColor::BLACK);
47                 SetColor(thread, bro, TreeColor::BLACK);
48                 SetColor(thread, GetParent(GetParent(index)), TreeColor::RED);
49                 index = GetParent(GetParent(index));
50             } else {
51                 if (IsRight(index)) {
52                     index = GetParent(index);
53                     LeftRotate(thread, index);
54                 }
55                 SetColor(thread, GetParent(index), TreeColor::BLACK);
56                 SetColor(thread, GetParent(GetParent(index)), TreeColor::RED);
57                 RightRotate(thread, GetParent(GetParent(index)));
58             }
59         } else {
60             int bro = GetRightBrother(GetParent(index));
61             if (GetColor(bro)) {
62                 SetColor(thread, GetParent(index), TreeColor::BLACK);
63                 SetColor(thread, bro, TreeColor::BLACK);
64                 SetColor(thread, GetParent(GetParent(index)), TreeColor::RED);
65                 index = GetParent(GetParent(index));
66             } else {
67                 if (IsLeft(index)) {
68                     index = GetParent(index);
69                     RightRotate(thread, index);
70                 }
71                 SetColor(thread, GetParent(index), TreeColor::BLACK);
72                 SetColor(thread, GetParent(GetParent(index)), TreeColor::RED);
73                 LeftRotate(thread, GetParent(GetParent(index)));
74             }
75         }
76     }
77     SetColor(thread, GetRootEntries(), TreeColor::BLACK);
78 }
79 
80 template<typename Derived>
LeftRotate(const JSThread * thread,int index)81 void TaggedTree<Derived>::LeftRotate(const JSThread *thread, int index)
82 {
83     if (index >= 0) {
84         int right = GetRightChild(index).GetInt();
85         JSTaggedValue leftOfRight = GetLeftChild(right);
86         SetRightChild(thread, index, leftOfRight);
87         if (!leftOfRight.IsHole()) {
88             SetParent(thread, leftOfRight.GetInt(), JSTaggedValue(index));
89         }
90         int parentOfIndex = GetParent(index);
91         SetParent(thread, right, JSTaggedValue(parentOfIndex));
92         if (parentOfIndex < 0) {
93             SetRootEntries(thread, right);
94         } else {
95             JSTaggedValue left = GetLeftChild(parentOfIndex);
96             if (!left.IsHole() && left.GetInt() == index) { // change to isleft
97                 SetLeftChild(thread, parentOfIndex, JSTaggedValue(right));
98             } else {
99                 SetRightChild(thread, parentOfIndex, JSTaggedValue(right));
100             }
101         }
102         SetLeftChild(thread, right, JSTaggedValue(index));
103         SetParent(thread, index, JSTaggedValue(right));
104     }
105 }
106 
107 template<typename Derived>
RightRotate(const JSThread * thread,int index)108 void TaggedTree<Derived>::RightRotate(const JSThread *thread, int index)
109 {
110     if (index >= 0) {
111         int left = GetLeftChild(index).GetInt();
112         JSTaggedValue rightOfLeft = GetRightChild(left);
113         SetLeftChild(thread, index, rightOfLeft);
114         if (!rightOfLeft.IsHole()) {
115             SetParent(thread, rightOfLeft.GetInt(), JSTaggedValue(index));
116         }
117         int parentOfIndex = GetParent(index);
118         SetParent(thread, left, JSTaggedValue(parentOfIndex));
119         if (parentOfIndex < 0) {
120             SetRootEntries(thread, left);
121         } else {
122             JSTaggedValue right = GetRightChild(parentOfIndex);
123             if (!right.IsHole() && right.GetInt() == index) { // change to isright
124                 SetRightChild(thread, parentOfIndex, JSTaggedValue(left));
125             } else {
126                 SetLeftChild(thread, parentOfIndex, JSTaggedValue(left));
127             }
128         }
129         SetRightChild(thread, left, JSTaggedValue(index));
130         SetParent(thread, index, JSTaggedValue(left));
131     }
132 }
133 
134 template<typename Derived>
AdjustTaggedTree(const JSThread * thread,const JSHandle<Derived> & tree,int len)135 JSHandle<Derived> TaggedTree<Derived>::AdjustTaggedTree(const JSThread *thread, const JSHandle<Derived> &tree, int len)
136 {
137     JSMutableHandle<Derived> newTree(thread, JSTaggedValue::Undefined());
138     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
139     if (tree->NumberOfDeletedElements() == 0) {
140         newTree.Update(factory->ExtendArray(JSHandle<TaggedArray>::Cast(tree), len).GetTaggedValue());
141         return newTree;
142     }
143 
144     uint32_t elements = tree->NumberOfElements();
145     newTree.Update(factory->NewTaggedArray(len).GetTaggedValue());
146     newTree->SetNumberOfElements(thread, elements);
147     newTree->SetNumberOfDeletedElements(thread, 0);
148 
149     newTree->SetRootEntries(thread, 0);
150     CQueue<int> entries;
151     entries.push(tree->GetRootEntries());
152     int index = 0;
153     newTree->SetParent(thread, index, JSTaggedValue(-1));
154     int child = 1;
155     while (!entries.empty()) {
156         int parent = entries.front();
157         JSTaggedValue left = tree->GetLeftChild(parent);
158         if (!left.IsHole()) {
159             entries.push(left.GetInt());
160             newTree->SetLeftChild(thread, index, JSTaggedValue(child));
161             newTree->SetParent(thread, child++, JSTaggedValue(index));
162         }
163         JSTaggedValue right = tree->GetRightChild(parent);
164         if (!right.IsHole()) {
165             entries.push(right.GetInt());
166             newTree->SetRightChild(thread, index, JSTaggedValue(child));
167             newTree->SetParent(thread, child++, JSTaggedValue(index));
168         }
169         tree->CopyEntry(thread, parent, newTree, index);
170         entries.pop();
171         index++;
172     }
173     return newTree;
174 }
175 
176 template<typename Derived>
Transplant(const JSThread * thread,int dst,int src)177 void TaggedTree<Derived>::Transplant(const JSThread *thread, int dst, int src)
178 {
179     int parent = GetParent(dst);
180     if (parent < 0) {
181         SetRootEntries(thread, src);
182     } else if (IsLeft(dst)) {
183         JSTaggedValue child = src < 0 ? JSTaggedValue::Hole() : JSTaggedValue(src);
184         SetLeftChild(thread, parent, child);
185     } else {
186         JSTaggedValue child = src < 0 ? JSTaggedValue::Hole() : JSTaggedValue(src);
187         SetRightChild(thread, parent, child);
188     }
189     SetParent(thread, src, JSTaggedValue(parent));
190 }
191 
192 template<typename Derived>
Remove(const JSThread * thread,const JSHandle<Derived> & tree,int entry)193 void TaggedTree<Derived>::Remove(const JSThread *thread, const JSHandle<Derived> &tree, int entry)
194 {
195     int successor = entry;
196     if (!tree->GetLeftChild(entry).IsHole() && !tree->GetRightChild(entry).IsHole()) {
197         successor = tree->GetSuccessor(entry);
198         tree->CopyData(thread, entry, successor);
199     }
200     JSTaggedValue left = tree->GetLeftChild(successor);
201     JSTaggedValue right = tree->GetRightChild(successor);
202     int child = left.IsHole() ? (right.IsHole() ? -1 : right.GetInt()) : left.GetInt();
203     if (child < 0) {
204         if (tree->GetColor(successor) == TreeColor::BLACK) {
205             tree->DeleteRebalance(thread, successor);
206         }
207     }
208     tree->Transplant(thread, successor, child);
209 
210     if (child >= 0) {
211         if (tree->GetColor(successor) == TreeColor::BLACK) {
212             tree->DeleteRebalance(thread, child);
213         }
214     }
215     tree->RemoveEntry(thread, successor);
216     tree->SetNumberOfElements(thread, tree->NumberOfElements() - 1);
217     tree->SetNumberOfDeletedElements(thread, tree->NumberOfDeletedElements() + 1);
218 }
219 
220 template<typename Derived>
DeleteRebalance(const JSThread * thread,int index)221 void TaggedTree<Derived>::DeleteRebalance(const JSThread *thread, int index)
222 {
223     while (index != GetRootEntries() && GetColor(index) == TreeColor::BLACK) {
224         if (IsLeft(index)) {
225             int bro = GetLeftBrother(index);
226             if (GetColor(bro)) {
227                 SetColor(thread, bro, TreeColor::BLACK);
228                 SetColor(thread, GetParent(index), TreeColor::RED);
229                 LeftRotate(thread, GetParent(index));
230                 bro = GetLeftBrother(index);
231             }
232             if (GetColor(GetLeftChildIndex(bro)) == TreeColor::BLACK &&
233                 GetColor(GetRightChildIndex(bro)) == TreeColor::BLACK) {
234                 SetColor(thread, bro, TreeColor::RED);
235                 index = GetParent(index);
236             } else {
237                 if (GetColor(GetRightChildIndex(bro)) == TreeColor::BLACK) {
238                     SetColor(thread, GetLeftChildIndex(bro), TreeColor::BLACK);
239                     SetColor(thread, bro, TreeColor::RED);
240                     RightRotate(thread, bro);
241                     bro = GetLeftBrother(index);
242                 }
243                 SetColor(thread, bro, GetColor(GetParent(index)));
244                 SetColor(thread, GetParent(index), TreeColor::BLACK);
245                 SetColor(thread, GetRightChildIndex(bro), TreeColor::BLACK);
246                 LeftRotate(thread, GetParent(index));
247                 index = GetRootEntries();
248             }
249         } else {
250             int bro = GetRightBrother(index);
251             if (GetColor(bro)) {
252                 SetColor(thread, bro, TreeColor::BLACK);
253                 SetColor(thread, GetParent(index), TreeColor::RED);
254                 RightRotate(thread, GetParent(index));
255                 bro = GetRightBrother(index);
256             }
257             if (GetColor(GetRightChildIndex(bro)) == TreeColor::BLACK &&
258                 GetColor(GetLeftChildIndex(bro)) == TreeColor::BLACK) {
259                 SetColor(thread, bro, TreeColor::RED);
260                 index = GetParent(index);
261             } else {
262                 if (GetColor(GetLeftChildIndex(bro)) == TreeColor::BLACK) {
263                     SetColor(thread, GetRightChildIndex(bro), TreeColor::BLACK);
264                     SetColor(thread, bro, TreeColor::RED);
265                     LeftRotate(thread, bro);
266                     bro = GetRightBrother(index);
267                 }
268                 SetColor(thread, bro, GetColor(GetParent(index)));
269                 SetColor(thread, GetParent(index), TreeColor::BLACK);
270                 SetColor(thread, GetLeftChildIndex(bro), TreeColor::BLACK);
271                 RightRotate(thread, GetParent(index));
272                 index = GetRootEntries();
273             }
274         }
275     }
276     SetColor(thread, index, TreeColor::BLACK);
277 }
278 
279 template<typename Derived>
GetPreDecessor(int entry) const280 int TaggedTree<Derived>::GetPreDecessor(int entry) const
281 {
282     int child = GetLeftChildIndex(entry);
283     if (child >= 0) {
284         return GetMaximum(child);
285     }
286     int parent = GetParent(entry);
287     while (parent >= 0 && (GetLeftChildIndex(parent) == entry)) {
288         entry = parent;
289         parent = GetParent(entry);
290     }
291     return parent;
292 }
293 
294 template<typename Derived>
GetSuccessor(int entry) const295 int TaggedTree<Derived>::GetSuccessor(int entry) const
296 {
297     int child = GetRightChildIndex(entry);
298     if (child >= 0) {
299         return GetMinimum(child);
300     }
301     int parent = GetParent(entry);
302     while (parent >= 0 && (GetRightChildIndex(parent) == entry)) {
303         entry = parent;
304         parent = GetParent(entry);
305     }
306     return parent;
307 }
308 
309 template<typename Derived>
FindEntry(JSThread * thread,const JSHandle<Derived> & tree,const JSHandle<JSTaggedValue> & key)310 int TaggedTree<Derived>::FindEntry(JSThread *thread, const JSHandle<Derived> &tree, const JSHandle<JSTaggedValue> &key)
311 {
312     int parentIndex = tree->GetRootEntries();
313     JSMutableHandle<JSTaggedValue> parentKey(thread, tree->GetKey(parentIndex));
314     ComparisonResult res;
315     while (!parentKey->IsHole()) {
316         res = EntryCompare(thread, key, parentKey, tree);
317         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, 0);
318         if (res == ComparisonResult::EQUAL) {
319             return parentIndex;
320         } else if (res == ComparisonResult::LESS) {
321             JSTaggedValue child = tree->GetLeftChild(parentIndex);
322             if (child.IsHole()) {
323                 break;
324             }
325             parentIndex = child.GetInt();
326         } else {
327             JSTaggedValue child = tree->GetRightChild(parentIndex);
328             if (child.IsHole()) {
329                 break;
330             }
331             parentIndex = child.GetInt();
332         }
333         parentKey.Update(tree->GetKey(parentIndex));
334     }
335     return -1;
336 }
337 
338 template<typename Derived>
GetSortArray(const JSThread * thread,const JSHandle<Derived> & tree)339 JSHandle<TaggedArray> TaggedTree<Derived>::GetSortArray(const JSThread *thread, const JSHandle<Derived> &tree)
340 {
341     JSHandle<TaggedArray> sortArray = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(tree->NumberOfElements());
342     CStack<int> entries;
343     int index = tree->GetRootEntries();
344     int aid = 0;
345     while (index >= 0 || !entries.empty()) {
346         while (index >= 0) {
347             entries.emplace(index);
348             index = tree->GetLeftChildIndex(index);
349         }
350         if (!entries.empty()) {
351             sortArray->Set(thread, aid++, JSTaggedValue(entries.top()));
352             index = tree->GetRightChildIndex(entries.top());
353             entries.pop();
354         }
355     }
356     return sortArray;
357 }
358 
359 template<typename Derived>
Insert(JSThread * thread,JSHandle<Derived> & tree,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)360 JSHandle<Derived> TaggedTree<Derived>::Insert(JSThread *thread, JSHandle<Derived> &tree,
361                                               const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value)
362 {
363     ASSERT(IsKey(key.GetTaggedValue()));
364     JSMutableHandle<JSTaggedValue> parentKey(thread, tree->GetRootKey());
365     if (parentKey->IsHole()) {
366         tree->SetRoot(thread, 0, key.GetTaggedValue(), value.GetTaggedValue());
367         tree->SetNumberOfElements(thread, tree->NumberOfElements() + 1);
368         return tree;
369     }
370 
371     JSHandle<Derived> newTree = GrowCapacity(thread, tree);
372     int parentIndex = newTree->GetRootEntries();
373     ComparisonResult res;
374     while (!parentKey->IsHole()) {
375         res = EntryCompare(thread, key, parentKey, tree);
376         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSHandle<Derived>(thread, JSTaggedValue::Exception()));
377         if (res == ComparisonResult::EQUAL) {
378             newTree->SetValue(thread, parentIndex, value.GetTaggedValue());
379             return tree;
380         } else if (res == ComparisonResult::LESS) {
381             JSTaggedValue child = newTree->GetLeftChild(parentIndex);
382             if (child.IsHole()) {
383                 break;
384             }
385             parentIndex = child.GetInt();
386         } else {
387             JSTaggedValue child = newTree->GetRightChild(parentIndex);
388             if (child.IsHole()) {
389                 break;
390             }
391             parentIndex = child.GetInt();
392         }
393         parentKey.Update(newTree->GetKey(parentIndex));
394     }
395 
396     uint32_t entry = newTree->NumberOfElements() + newTree->NumberOfDeletedElements();
397     if (res != ComparisonResult::LESS) {
398         newTree->InsertRightEntry(thread, parentIndex, entry, key.GetTaggedValue(), value.GetTaggedValue());
399     } else {
400         newTree->InsertLeftEntry(thread, parentIndex, entry, key.GetTaggedValue(), value.GetTaggedValue());
401     }
402     newTree->SetNumberOfElements(thread, newTree->NumberOfElements() + 1);
403     newTree->InsertRebalance(thread, entry);
404     return newTree;
405 }
406 
407 template<typename Derived>
GrowCapacity(const JSThread * thread,JSHandle<Derived> & tree)408 JSHandle<Derived> TaggedTree<Derived>::GrowCapacity(const JSThread *thread, JSHandle<Derived> &tree)
409 {
410     uint32_t nof = tree->NumberOfElements() + tree->NumberOfDeletedElements();
411     int oldCapacity = tree->Capacity();
412     if (static_cast<int>(nof + 1) <= oldCapacity) {
413         return tree;
414     }
415 
416     int newCapacity = ComputeCapacity(oldCapacity);
417     int length = ELEMENTS_START_INDEX + newCapacity * (Derived::ENTRY_SIZE);
418     JSHandle<Derived> newTree = AdjustTaggedTree(thread, tree, length);
419     newTree->SetCapacity(thread, newCapacity);
420     return newTree;
421 }
422 
423 template<typename Derived>
GetLowerKey(JSThread * thread,const JSHandle<Derived> & tree,const JSHandle<JSTaggedValue> & key)424 JSTaggedValue TaggedTree<Derived>::GetLowerKey(JSThread *thread, const JSHandle<Derived> &tree,
425                                                const JSHandle<JSTaggedValue> &key)
426 {
427     int parentIndex = tree->GetRootEntries();
428     JSMutableHandle<JSTaggedValue> parentKey(thread, tree->GetKey(parentIndex));
429     int resultIndex = -1;
430     ComparisonResult res;
431     while (parentIndex >= 0) {
432         res = EntryCompare(thread, key, parentKey, tree);
433         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
434         if (res == ComparisonResult::GREAT) {
435             resultIndex = parentIndex;
436             parentIndex = tree->GetRightChildIndex(parentIndex);
437         } else {
438             parentIndex = tree->GetLeftChildIndex(parentIndex);
439         }
440         parentKey.Update(tree->GetKey(parentIndex));
441     }
442     JSTaggedValue lowerKey = tree->GetKey(resultIndex);
443     return tree->Transform(lowerKey);
444 }
445 
446 template<typename Derived>
GetHigherKey(JSThread * thread,const JSHandle<Derived> & tree,const JSHandle<JSTaggedValue> & key)447 JSTaggedValue TaggedTree<Derived>::GetHigherKey(JSThread *thread, const JSHandle<Derived> &tree,
448                                                 const JSHandle<JSTaggedValue> &key)
449 {
450     int parentIndex = tree->GetRootEntries();
451     JSMutableHandle<JSTaggedValue> parentKey(thread, tree->GetKey(parentIndex));
452     int resultIndex = -1;
453     ComparisonResult res;
454     while (parentIndex >= 0) {
455         res = EntryCompare(thread, key, parentKey, tree);
456         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
457         if (res == ComparisonResult::LESS) {
458             resultIndex = parentIndex;
459             parentIndex = tree->GetLeftChildIndex(parentIndex);
460         } else {
461             parentIndex = tree->GetRightChildIndex(parentIndex);
462         }
463         parentKey.Update(tree->GetKey(parentIndex));
464     }
465     JSTaggedValue lowerKey = tree->GetKey(resultIndex);
466     return tree->Transform(lowerKey);
467 }
468 
469 template<typename Derived>
Shrink(const JSThread * thread,const JSHandle<Derived> & tree)470 JSHandle<Derived> TaggedTree<Derived>::Shrink(const JSThread *thread, const JSHandle<Derived> &tree)
471 {
472     int oldCapacity = static_cast<int>(tree->Capacity());
473     if (static_cast<int>(tree->NumberOfElements()) >= (oldCapacity + 1) / 4) { // 4: quarter
474         return tree;
475     }
476     uint32_t newCapacity = static_cast<uint32_t>(oldCapacity - 1) >> 1;
477     if (newCapacity < static_cast<uint32_t>(Derived::MIN_SHRINK_CAPACITY)) {
478         return tree;
479     }
480 
481     int length = ELEMENTS_START_INDEX + static_cast<int>(newCapacity) * (Derived::ENTRY_SIZE);
482     JSHandle<Derived> newTree = AdjustTaggedTree(thread, tree, length);
483     newTree->SetCapacity(thread, newCapacity);
484     return newTree;
485 }
486 
487 // TaggedTreeMap
Create(const JSThread * thread,int numberOfElements)488 JSTaggedValue TaggedTreeMap::Create(const JSThread *thread, int numberOfElements)
489 {
490     return RBTree::Create(thread, numberOfElements).GetTaggedValue();
491 }
492 
GetArrayFromMap(const JSThread * thread,const JSHandle<TaggedTreeMap> & map)493 JSHandle<TaggedArray> TaggedTreeMap::GetArrayFromMap(const JSThread *thread, const JSHandle<TaggedTreeMap> &map)
494 {
495     return RBTree::GetSortArray(thread, map);
496 }
497 
Set(JSThread * thread,JSHandle<TaggedTreeMap> & obj,const JSHandle<JSTaggedValue> & key,const JSHandle<JSTaggedValue> & value)498 JSTaggedValue TaggedTreeMap::Set(JSThread *thread, JSHandle<TaggedTreeMap> &obj,
499                                  const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value)
500 {
501     return RBTree::Insert(thread, obj, key, value).GetTaggedValue();
502 }
503 
Delete(JSThread * thread,const JSHandle<TaggedTreeMap> & map,int entry)504 JSTaggedValue TaggedTreeMap::Delete(JSThread *thread, const JSHandle<TaggedTreeMap> &map, int entry)
505 {
506     RBTree::Remove(thread, map, entry);
507     return RBTree::Shrink(thread, map).GetTaggedValue();
508 }
509 
HasValue(const JSThread * thread,JSTaggedValue value) const510 bool TaggedTreeMap::HasValue([[maybe_unused]] const JSThread *thread, JSTaggedValue value) const
511 {
512     int root = GetRootEntries();
513     if (root < 0) {
514         return false;
515     }
516 
517     CQueue<int> entries;
518     entries.push(root);
519     while (!entries.empty()) {
520         int parent = entries.front();
521         if (JSTaggedValue::SameValue(GetValue(parent), value)) {
522             return true;
523         }
524         int left = GetLeftChildIndex(parent);
525         if (left >= 0) {
526             entries.push(left);
527         }
528         int right = GetRightChildIndex(parent);
529         if (right >= 0) {
530             entries.push(right);
531         }
532         entries.pop();
533     }
534     return false;
535 }
536 
SetAll(JSThread * thread,JSHandle<TaggedTreeMap> & dst,const JSHandle<TaggedTreeMap> & src)537 JSTaggedValue TaggedTreeMap::SetAll(JSThread *thread, JSHandle<TaggedTreeMap> &dst, const JSHandle<TaggedTreeMap> &src)
538 {
539     CQueue<int> entries;
540     entries.push(src->GetRootEntries());
541     JSHandle<TaggedTreeMap> map = dst;
542     while (!entries.empty()) {
543         int parent = entries.front();
544         map = Insert(thread, map, JSHandle<JSTaggedValue>(thread, src->GetKey(parent)),
545                            JSHandle<JSTaggedValue>(thread, src->GetValue(parent)));
546         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
547         int left = src->GetLeftChildIndex(parent);
548         if (left >= 0) {
549             entries.push(left);
550         }
551         int right = src->GetRightChildIndex(parent);
552         if (right >= 0) {
553             entries.push(right);
554         }
555         entries.pop();
556     }
557     return map.GetTaggedValue();
558 }
559 
GetLowerKey(JSThread * thread,const JSHandle<TaggedTreeMap> & map,const JSHandle<JSTaggedValue> & key)560 JSTaggedValue TaggedTreeMap::GetLowerKey(JSThread *thread, const JSHandle<TaggedTreeMap> &map,
561                                          const JSHandle<JSTaggedValue> &key)
562 {
563     return RBTree::GetLowerKey(thread, map, key);
564 }
565 
GetHigherKey(JSThread * thread,const JSHandle<TaggedTreeMap> & map,const JSHandle<JSTaggedValue> & key)566 JSTaggedValue TaggedTreeMap::GetHigherKey(JSThread *thread, const JSHandle<TaggedTreeMap> &map,
567                                           const JSHandle<JSTaggedValue> &key)
568 {
569     return RBTree::GetHigherKey(thread, map, key);
570 }
571 
FindEntry(JSThread * thread,const JSHandle<TaggedTreeMap> & map,const JSHandle<JSTaggedValue> & key)572 int TaggedTreeMap::FindEntry(JSThread *thread, const JSHandle<TaggedTreeMap> &map, const JSHandle<JSTaggedValue> &key)
573 {
574     return RBTree::FindEntry(thread, map, key);
575 }
576 
577 // TaggedTreeSet
Create(const JSThread * thread,int numberOfElements)578 JSTaggedValue TaggedTreeSet::Create(const JSThread *thread, int numberOfElements)
579 {
580     return RBTree::Create(thread, numberOfElements).GetTaggedValue();
581 }
582 
GetArrayFromSet(const JSThread * thread,const JSHandle<TaggedTreeSet> & set)583 JSHandle<TaggedArray> TaggedTreeSet::GetArrayFromSet(const JSThread *thread, const JSHandle<TaggedTreeSet> &set)
584 {
585     return RBTree::GetSortArray(thread, set);
586 }
587 
Add(JSThread * thread,JSHandle<TaggedTreeSet> & obj,const JSHandle<JSTaggedValue> & value)588 JSTaggedValue TaggedTreeSet::Add(JSThread *thread, JSHandle<TaggedTreeSet> &obj, const JSHandle<JSTaggedValue> &value)
589 {
590     return RBTree::Insert(thread, obj, value, value).GetTaggedValue();
591 }
592 
Delete(JSThread * thread,const JSHandle<TaggedTreeSet> & set,int entry)593 JSTaggedValue TaggedTreeSet::Delete(JSThread *thread, const JSHandle<TaggedTreeSet> &set, int entry)
594 {
595     RBTree::Remove(thread, set, entry);
596     return RBTree::Shrink(thread, set).GetTaggedValue();
597 }
598 
GetLowerKey(JSThread * thread,const JSHandle<TaggedTreeSet> & set,const JSHandle<JSTaggedValue> & key)599 JSTaggedValue TaggedTreeSet::GetLowerKey(JSThread *thread, const JSHandle<TaggedTreeSet> &set,
600                                          const JSHandle<JSTaggedValue> &key)
601 {
602     return RBTree::GetLowerKey(thread, set, key);
603 }
604 
GetHigherKey(JSThread * thread,const JSHandle<TaggedTreeSet> & set,const JSHandle<JSTaggedValue> & key)605 JSTaggedValue TaggedTreeSet::GetHigherKey(JSThread *thread, const JSHandle<TaggedTreeSet> &set,
606                                           const JSHandle<JSTaggedValue> &key)
607 {
608     return RBTree::GetHigherKey(thread, set, key);
609 }
610 
FindEntry(JSThread * thread,const JSHandle<TaggedTreeSet> & set,const JSHandle<JSTaggedValue> & key)611 int TaggedTreeSet::FindEntry(JSThread *thread, const JSHandle<TaggedTreeSet> &set, const JSHandle<JSTaggedValue> &key)
612 {
613     return RBTree::FindEntry(thread, set, key);
614 }
615 }  // namespace panda::ecmascript
616