• 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 
16 #ifndef ECMASCRIPT_TAGGED_TREE_INL_H
17 #define ECMASCRIPT_TAGGED_TREE_INL_H
18 
19 #include "ecmascript/tagged_tree.h"
20 
21 #include "ecmascript/global_env.h"
22 #include "ecmascript/internal_call_params.h"
23 #include "tagged_array-inl.h"
24 #include "utils/bit_utils.h"
25 
26 namespace panda::ecmascript {
27 // TaggedTree
28 template<typename Derived>
GetRootKey()29 JSTaggedValue TaggedTree<Derived>::GetRootKey() const
30 {
31     return GetKey(GetRootEntries());
32 }
33 
34 template<typename Derived>
SetRoot(JSThread * thread,int index,JSTaggedValue key,JSTaggedValue value)35 void TaggedTree<Derived>::SetRoot(JSThread *thread, int index, JSTaggedValue key, JSTaggedValue value)
36 {
37     SetKey(thread, 0, key);
38     SetValue(thread, 0, value);
39     SetParent(thread, 0, JSTaggedValue(-1));
40     SetColor(thread, 0, TreeColor::BLACK);
41     SetRootEntries(thread, index);
42 }
43 
44 template<typename Derived>
SetKey(const JSThread * thread,uint32_t entry,JSTaggedValue key)45 void TaggedTree<Derived>::SetKey(const JSThread *thread, uint32_t entry, JSTaggedValue key)
46 {
47     uint32_t index = EntryToIndex(entry);
48     SetElement(thread, index, key);
49 }
50 
51 template<typename Derived>
SetValue(const JSThread * thread,uint32_t entry,JSTaggedValue value)52 void TaggedTree<Derived>::SetValue(const JSThread *thread, uint32_t entry, JSTaggedValue value)
53 {
54     uint32_t index = EntryToIndex(entry) + Derived::ENTRY_VALUE_INDEX;
55     SetElement(thread, index, value);
56 }
57 
58 template<typename Derived>
SetColor(const JSThread * thread,int entry,TreeColor color)59 void TaggedTree<Derived>::SetColor(const JSThread *thread, int entry, TreeColor color)
60 {
61     if (entry >= 0) {
62         uint32_t index = EntryToIndex(entry) + Derived::ENTRY_COLOR_INDEX;
63         SetElement(thread, index, JSTaggedValue(static_cast<int>(color)));
64     }
65 }
66 
67 template<typename Derived>
SetParent(const JSThread * thread,int entry,JSTaggedValue value)68 void TaggedTree<Derived>::SetParent(const JSThread *thread, int entry, JSTaggedValue value)
69 {
70     if (entry < 0) {
71         return;
72     }
73     uint32_t index = EntryToIndex(entry) + Derived::ENTRY_PARENT_INDEX;
74     SetElement(thread, index, value);
75 }
76 
77 template<typename Derived>
SetLeftChild(const JSThread * thread,uint32_t entry,JSTaggedValue value)78 void TaggedTree<Derived>::SetLeftChild(const JSThread *thread, uint32_t entry, JSTaggedValue value)
79 {
80     uint32_t index = EntryToIndex(entry) + Derived::ENTRY_LEFT_CHILD_INDEX;
81     SetElement(thread, index, value);
82 }
83 
84 template<typename Derived>
SetRightChild(const JSThread * thread,uint32_t entry,JSTaggedValue value)85 void TaggedTree<Derived>::SetRightChild(const JSThread *thread, uint32_t entry, JSTaggedValue value)
86 {
87     uint32_t index = EntryToIndex(entry) + Derived::ENTRY_RIGHT_CHILD_INDEX;
88     SetElement(thread, index, value);
89 }
90 
91 template<typename Derived>
SetCompare(const JSThread * thread,JSTaggedValue fn)92 void TaggedTree<Derived>::SetCompare(const JSThread *thread, JSTaggedValue fn)
93 {
94     Set(thread, COMPARE_FUNCTION_INDEX, fn);
95 }
96 
97 template<typename Derived>
GetCompare()98 JSTaggedValue TaggedTree<Derived>::GetCompare() const
99 {
100     return Get(COMPARE_FUNCTION_INDEX);
101 }
102 
103 template<typename Derived>
GetKey(int entry)104 JSTaggedValue TaggedTree<Derived>::GetKey(int entry) const
105 {
106     if (entry < 0) {
107         return JSTaggedValue::Hole();
108     }
109     int index = EntryToIndex(entry);
110     return GetElement(index);
111 }
112 
113 template<typename Derived>
GetValue(int entry)114 JSTaggedValue TaggedTree<Derived>::GetValue(int entry) const
115 {
116     int index = EntryToIndex(entry) + Derived::ENTRY_VALUE_INDEX;
117     return GetElement(index);
118 }
119 
120 template<typename Derived>
GetColor(int entry)121 TreeColor TaggedTree<Derived>::GetColor(int entry) const
122 {
123     if (entry < 0) {
124         return TreeColor::BLACK;
125     }
126     int index = EntryToIndex(entry) + Derived::ENTRY_COLOR_INDEX;
127     JSTaggedValue color = GetElement(index);
128     return color.GetInt() == TreeColor::RED ? TreeColor::RED : TreeColor::BLACK;
129 }
130 
131 template<typename Derived>
EntryToIndex(uint32_t entry)132 uint32_t TaggedTree<Derived>::EntryToIndex(uint32_t entry) const
133 {
134     return ELEMENTS_START_INDEX + entry * (Derived::ENTRY_SIZE);
135 }
136 
137 template<typename Derived>
SetElement(const JSThread * thread,uint32_t index,JSTaggedValue element)138 void TaggedTree<Derived>::SetElement(const JSThread *thread, uint32_t index, JSTaggedValue element)
139 {
140     ASSERT(index >= 0 && index < GetLength());
141     Set(thread, index, element);
142 }
143 
144 template<typename Derived>
GetElement(int index)145 JSTaggedValue TaggedTree<Derived>::GetElement(int index) const
146 {
147     ASSERT(index >= 0 && index < static_cast<int>(GetLength()));
148     return Get(index);
149 }
150 
151 template<typename Derived>
NumberOfElements()152 int TaggedTree<Derived>::NumberOfElements() const
153 {
154     return Get(NUMBER_OF_ELEMENTS_INDEX).GetInt();
155 }
156 
157 template<typename Derived>
NumberOfDeletedElements()158 int TaggedTree<Derived>::NumberOfDeletedElements() const
159 {
160     return Get(NUMBER_OF_HOLE_ENTRIES_INDEX).GetInt();
161 }
162 
163 template<typename Derived>
SetNumberOfElements(const JSThread * thread,int num)164 void TaggedTree<Derived>::SetNumberOfElements(const JSThread *thread, int num)
165 {
166     Set(thread, NUMBER_OF_ELEMENTS_INDEX, JSTaggedValue(num));
167 }
168 
169 template<typename Derived>
SetNumberOfDeletedElements(const JSThread * thread,int num)170 void TaggedTree<Derived>::SetNumberOfDeletedElements(const JSThread *thread, int num)
171 {
172     Set(thread, NUMBER_OF_HOLE_ENTRIES_INDEX, JSTaggedValue(num));
173 }
174 
175 template<typename Derived>
SetRootEntries(const JSThread * thread,int num)176 void TaggedTree<Derived>::SetRootEntries(const JSThread *thread, int num)
177 {
178     Set(thread, ROOT_INDEX, JSTaggedValue(num));
179 }
180 
181 template<typename Derived>
GetRootEntries()182 int TaggedTree<Derived>::GetRootEntries() const
183 {
184     return Get(ROOT_INDEX).GetInt();
185 }
186 
187 template<typename Derived>
GetLeftChild(int parent)188 JSTaggedValue TaggedTree<Derived>::GetLeftChild(int parent) const
189 {
190     if (parent < 0) {
191         return JSTaggedValue::Hole();
192     }
193     int index = EntryToIndex(parent) + Derived::ENTRY_LEFT_CHILD_INDEX;
194     return Get(index);
195 }
196 
197 template<typename Derived>
GetRightChild(int parent)198 JSTaggedValue TaggedTree<Derived>::GetRightChild(int parent) const
199 {
200     if (parent < 0) {
201         return JSTaggedValue::Hole();
202     }
203     int index = EntryToIndex(parent) + Derived::ENTRY_RIGHT_CHILD_INDEX;
204     return Get(index);
205 }
206 
207 template<typename Derived>
GetLeftChildIndex(int parent)208 int TaggedTree<Derived>::GetLeftChildIndex(int parent) const
209 {
210     if (parent < 0) {
211         return -1;
212     }
213     int index = EntryToIndex(parent) + Derived::ENTRY_LEFT_CHILD_INDEX;
214     JSTaggedValue child = Get(index);
215     return child.IsHole() ? -1 : child.GetInt();
216 }
217 
218 template<typename Derived>
GetRightChildIndex(int parent)219 int TaggedTree<Derived>::GetRightChildIndex(int parent) const
220 {
221     if (parent < 0) {
222         return -1;
223     }
224     int index = EntryToIndex(parent) + Derived::ENTRY_RIGHT_CHILD_INDEX;
225     JSTaggedValue child = Get(index);
226     return child.IsHole() ? -1: child.GetInt();
227 }
228 
229 template<typename Derived>
GetParent(int entry)230 int TaggedTree<Derived>::GetParent(int entry) const
231 {
232     int index = EntryToIndex(entry) + Derived::ENTRY_PARENT_INDEX;
233     JSTaggedValue parent = GetElement(index);
234     return parent.GetInt();
235 }
236 
237 template<typename Derived>
GetMinimum(int entry)238 int TaggedTree<Derived>::GetMinimum(int entry) const
239 {
240     JSTaggedValue child = GetLeftChild(entry);
241     while (!child.IsHole()) {
242         entry = child.GetInt();
243         child = GetLeftChild(entry);
244     }
245     return entry;
246 }
247 
248 template<typename Derived>
GetMaximum(int entry)249 int TaggedTree<Derived>::GetMaximum(int entry) const
250 {
251     JSTaggedValue child = GetRightChild(entry);
252     while (!child.IsHole()) {
253         entry = child.GetInt();
254         child = GetRightChild(entry);
255     }
256     return entry;
257 }
258 
259 template<typename Derived>
IsLeft(int entry)260 bool TaggedTree<Derived>::IsLeft(int entry) const
261 {
262     JSTaggedValue child = GetLeftChild(GetParent(entry));
263     return child.IsHole() ? false : (child.GetInt() == entry);
264 }
265 
266 template<typename Derived>
IsRight(int entry)267 bool TaggedTree<Derived>::IsRight(int entry) const
268 {
269     JSTaggedValue child = GetRightChild(GetParent(entry));
270     return child.IsHole() ? false : (child.GetInt() == entry);
271 }
272 
273 template<typename Derived>
IsVaildIndex(int entry)274 bool TaggedTree<Derived>::IsVaildIndex(int entry) const
275 {
276     return entry != GetRootEntries() && !GetKey(entry).IsHole();
277 }
278 
279 template<typename Derived>
GetLeftBrother(int entry)280 int TaggedTree<Derived>::GetLeftBrother(int entry) const
281 {
282     JSTaggedValue child = GetRightChild(GetParent(entry));
283     return child.IsHole() ? -1 : child.GetInt();
284 }
285 
286 template<typename Derived>
GetRightBrother(int entry)287 int TaggedTree<Derived>::GetRightBrother(int entry) const
288 {
289     JSTaggedValue child = GetLeftChild(GetParent(entry));
290     return child.IsHole() ? -1 : child.GetInt();
291 }
292 
293 template<typename Derived>
SetCapacity(const JSThread * thread,int capacity)294 void TaggedTree<Derived>::SetCapacity(const JSThread *thread, int capacity)
295 {
296     Set(thread, CAPACITY_INDEX, JSTaggedValue(capacity));
297 }
298 
299 template<typename Derived>
Capacity()300 int TaggedTree<Derived>::Capacity() const
301 {
302     return Get(CAPACITY_INDEX).GetInt();
303 }
304 
305 template<typename Derived>
ComputeCapacity(int oldCapacity)306 int TaggedTree<Derived>::ComputeCapacity(int oldCapacity)
307 {
308     int capacity = (oldCapacity << 1) + 1;
309     return (capacity > MIN_CAPACITY) ? capacity : MIN_CAPACITY;
310 }
311 
312 template<typename Derived>
InsertLeftEntry(const JSThread * thread,uint32_t parentIndex,uint32_t entry,JSTaggedValue key,JSTaggedValue value)313 void TaggedTree<Derived>::InsertLeftEntry(const JSThread *thread, uint32_t parentIndex, uint32_t entry,
314                                           JSTaggedValue key, JSTaggedValue value)
315 {
316     SetKey(thread, entry, key);
317     SetValue(thread, entry, value);
318     SetColor(thread, entry, TreeColor::RED);
319     SetParent(thread, entry, JSTaggedValue(parentIndex));
320     SetLeftChild(thread, parentIndex, JSTaggedValue(entry));
321 }
322 
323 template<typename Derived>
InsertRightEntry(const JSThread * thread,uint32_t parentIndex,uint32_t entry,JSTaggedValue key,JSTaggedValue value)324 void TaggedTree<Derived>::InsertRightEntry(const JSThread *thread, uint32_t parentIndex, uint32_t entry,
325                                            JSTaggedValue key, JSTaggedValue value)
326 {
327     SetKey(thread, entry, key);
328     SetValue(thread, entry, value);
329     SetColor(thread, entry, TreeColor::RED);
330     SetParent(thread, entry, JSTaggedValue(parentIndex));
331     SetRightChild(thread, parentIndex, JSTaggedValue(entry));
332 }
333 
334 template<typename Derived>
CopyEntry(const JSThread * thread,int parent,const JSHandle<Derived> & newTree,int index)335 void TaggedTree<Derived>::CopyEntry(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index)
336 {
337     newTree->SetKey(thread, index, GetKey(parent));
338     newTree->SetColor(thread, index, GetColor(parent));
339 }
340 
341 template<typename Derived>
CopyData(const JSThread * thread,int dst,int src)342 void TaggedTree<Derived>::CopyData(const JSThread *thread, int dst, int src)
343 {
344     SetKey(thread, dst, GetKey(src));
345 }
346 
347 template<typename Derived>
CopyAllData(const JSThread * thread,int parent,const JSHandle<Derived> & newTree,int index)348 void TaggedTree<Derived>::CopyAllData(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index)
349 {
350     newTree->SetKey(thread, index, GetKey(parent));
351     newTree->SetValue(thread, index, GetValue(parent));
352     newTree->SetColor(thread, index, GetColor(parent));
353     newTree->SetParent(thread, index, JSTaggedValue(GetParent(parent)));
354     newTree->SetRightChild(thread, index, GetRightChild(parent));
355     newTree->SetLeftChild(thread, index, GetLeftChild(parent));
356 }
357 
358 template<typename Derived>
RemoveEntry(const JSThread * thread,int index)359 void TaggedTree<Derived>::RemoveEntry(const JSThread *thread, int index)
360 {
361     SetKey(thread, index, JSTaggedValue::Hole());
362     SetParent(thread, index, JSTaggedValue::Hole());
363     SetLeftChild(thread, index, JSTaggedValue::Hole());
364     SetRightChild(thread, index, JSTaggedValue::Hole());
365 }
366 
367 template<typename Derived>
EntryCompare(JSThread * thread,const JSHandle<JSTaggedValue> valueX,const JSHandle<JSTaggedValue> valueY,JSHandle<Derived> tree)368 ComparisonResult TaggedTree<Derived>::EntryCompare(JSThread *thread, const JSHandle<JSTaggedValue> valueX,
369                                                    const JSHandle<JSTaggedValue> valueY, JSHandle<Derived> tree)
370 {
371     JSTaggedValue fn = tree->GetCompare();
372     if (fn.IsHole()) {
373         return OrdinayEntryCompare(thread, valueX, valueY);
374     }
375 
376     JSHandle<JSTaggedValue> compareFn(thread, fn);
377     JSHandle<JSTaggedValue> thisArgHandle = thread->GlobalConstants()->GetHandledUndefined();
378     InternalCallParams *arguments = thread->GetInternalCallParams();
379     arguments->MakeArgv(valueX, valueY);
380     JSTaggedValue callResult =
381         JSFunction::Call(thread, compareFn, thisArgHandle, 2, arguments->GetArgv());  // 2: two args
382     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
383     int compareResult = 0;
384     if (callResult.IsInt()) {
385         compareResult = callResult.GetInt();
386     } else {
387         JSHandle<JSTaggedValue> resultHandle(thread, callResult);
388         JSTaggedNumber v = JSTaggedValue::ToNumber(thread, resultHandle);
389         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, ComparisonResult::UNDEFINED);
390         double value = v.GetNumber();
391         if (std::isnan(value)) {
392             THROW_TYPE_ERROR_AND_RETURN(thread, "CompareFn has illegal return value", ComparisonResult::UNDEFINED);
393         }
394         compareResult = static_cast<int>(value);
395     }
396     return compareResult > 0 ? ComparisonResult::GREAT :
397                                (compareResult < 0 ? ComparisonResult::LESS : ComparisonResult::EQUAL);
398 }
399 
400 template<typename Derived>
OrdinayEntryCompare(JSThread * thread,const JSHandle<JSTaggedValue> valueX,const JSHandle<JSTaggedValue> valueY)401 ComparisonResult TaggedTree<Derived>::OrdinayEntryCompare(JSThread *thread, const JSHandle<JSTaggedValue> valueX,
402                                                           const JSHandle<JSTaggedValue> valueY)
403 {
404     if (valueX->IsString() && valueY->IsString()) {
405         auto xString = static_cast<EcmaString *>(valueX->GetTaggedObject());
406         auto yString = static_cast<EcmaString *>(valueY->GetTaggedObject());
407         int result = xString->Compare(yString);
408         if (result < 0) {
409             return ComparisonResult::LESS;
410         }
411         if (result == 0) {
412             return ComparisonResult::EQUAL;
413         }
414         return ComparisonResult::GREAT;
415     }
416 
417     if (valueX->IsNumber() && valueY->IsNumber()) {
418         return JSTaggedValue::StrictNumberCompare(valueX->GetNumber(), valueY->GetNumber());
419     }
420 
421     if (valueX->IsNumber() && valueY->IsString()) {
422         return ComparisonResult::LESS;
423     }
424     if (valueX->IsString() && valueY->IsNumber()) {
425         return ComparisonResult::GREAT;
426     }
427 
428     JSHandle<JSTaggedValue> xValueHandle(JSTaggedValue::ToString(thread, valueX));
429     JSHandle<JSTaggedValue> yValueHandle(JSTaggedValue::ToString(thread, valueY));
430     ASSERT_NO_ABRUPT_COMPLETION(thread);
431     return JSTaggedValue::Compare(thread, xValueHandle, yValueHandle);
432 }
433 
434 template<typename Derived>
Transform(JSTaggedValue v)435 JSTaggedValue TaggedTree<Derived>::Transform(JSTaggedValue v) const
436 {
437     return v.IsHole() ? JSTaggedValue::Undefined() : v;
438 }
439 
440 // TaggedTreeMap
CopyEntry(const JSThread * thread,int parent,const JSHandle<TaggedTreeMap> & newMap,int index)441 void TaggedTreeMap::CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeMap> &newMap, int index)
442 {
443     RBTree::CopyEntry(thread, parent, newMap, index);
444     newMap->SetValue(thread, index, GetValue(parent));
445 }
446 
CopyData(const JSThread * thread,int dst,int src)447 void TaggedTreeMap::CopyData(const JSThread *thread, int dst, int src)
448 {
449     RBTree::CopyData(thread, dst, src);
450     SetValue(thread, dst, GetValue(src));
451 }
452 
RemoveEntry(const JSThread * thread,int index)453 void TaggedTreeMap::RemoveEntry(const JSThread *thread, int index)
454 {
455     RBTree::RemoveEntry(thread, index);
456     SetValue(thread, index, JSTaggedValue::Hole());
457 }
458 
Get(JSThread * thread,const JSHandle<TaggedTreeMap> & map,const JSHandle<JSTaggedValue> & key)459 JSTaggedValue TaggedTreeMap::Get(JSThread *thread, const JSHandle<TaggedTreeMap> &map,
460                                  const JSHandle<JSTaggedValue> &key)
461 {
462     int index = RBTree::FindEntry(thread, map, key);
463     return index == -1 ? JSTaggedValue::Undefined() : map->GetValue(index);
464 }
465 
GetFirstKey()466 JSTaggedValue TaggedTreeMap::GetFirstKey() const
467 {
468     JSTaggedValue key = GetKey(GetMinimum(GetRootEntries()));
469     return Transform(key);
470 }
471 
GetLastKey()472 JSTaggedValue TaggedTreeMap::GetLastKey() const
473 {
474     JSTaggedValue key = GetKey(GetMaximum(GetRootEntries()));
475     return Transform(key);
476 }
477 
478 // TaggedTreeSet
CopyEntry(const JSThread * thread,int parent,const JSHandle<TaggedTreeSet> & newMap,int index)479 void TaggedTreeSet::CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeSet> &newMap, int index)
480 {
481     RBTree::CopyEntry(thread, parent, newMap, index);
482     newMap->SetValue(thread, index, GetValue(parent));
483 }
484 
CopyData(const JSThread * thread,int dst,int src)485 void TaggedTreeSet::CopyData(const JSThread *thread, int dst, int src)
486 {
487     RBTree::CopyData(thread, dst, src);
488     SetValue(thread, dst, GetValue(src));
489 }
490 
RemoveEntry(const JSThread * thread,int index)491 void TaggedTreeSet::RemoveEntry(const JSThread *thread, int index)
492 {
493     RBTree::RemoveEntry(thread, index);
494     SetValue(thread, index, JSTaggedValue::Hole());
495 }
496 
GetFirstKey()497 JSTaggedValue TaggedTreeSet::GetFirstKey() const
498 {
499     JSTaggedValue key = GetKey(GetMinimum(GetRootEntries()));
500     return Transform(key);
501 }
502 
GetLastKey()503 JSTaggedValue TaggedTreeSet::GetLastKey() const
504 {
505     JSTaggedValue key = GetKey(GetMaximum(GetRootEntries()));
506     return Transform(key);
507 }
508 }  // namespace panda::ecmascript
509 #endif  // ECMASCRIPT_TAGGED_TREE_INL_H
510