1 /* 2 * Copyright (c) 2022-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 ECMASCRIPT_TAGGED_TREE_H 17 #define ECMASCRIPT_TAGGED_TREE_H 18 19 #include "ecmascript/global_env.h" 20 #include "ecmascript/js_tagged_value.h" 21 #include "ecmascript/js_handle.h" 22 #include "ecmascript/tagged_array-inl.h" 23 24 namespace panda::ecmascript { 25 enum TreeColor : uint8_t { BLACK = 0, RED }; 26 /** 27 * The tree layout is as follows: 28 * 1.array[0-4] is used to store common information, such as: 29 * +------------------------+-----------------------------+------------------------+------------+------------------+ 30 * | the number of elements | the number of hole elements | the number of capacity | root index | compare function | 31 * +------------------------+-----------------------------+------------------------+------------+------------------+ 32 * 2.array[5,5+capacity] is used to store node of tree, map and set store nodes in different formats respectively. 33 * */ 34 template<typename Derived> 35 class TaggedTree : public TaggedArray { 36 public: 37 static constexpr int MIN_CAPACITY = 7; 38 static constexpr int NUMBER_OF_ELEMENTS_INDEX = 0; 39 static constexpr int NUMBER_OF_HOLE_ENTRIES_INDEX = 1; 40 static constexpr int CAPACITY_INDEX = 2; 41 static constexpr int ROOT_INDEX = 3; 42 static constexpr int COMPARE_FUNCTION_INDEX = 4; 43 static constexpr int ELEMENTS_START_INDEX = 5; 44 static constexpr int MIN_SHRINK_CAPACITY = 15; 45 46 static JSHandle<Derived> Create(const JSThread *thread, int numberOfElements); 47 48 static JSHandle<Derived> Insert(JSThread *thread, JSHandle<Derived> &tree, const JSHandle<JSTaggedValue> &key, 49 const JSHandle<JSTaggedValue> &value); 50 51 static JSHandle<Derived> GrowCapacity(const JSThread *thread, JSHandle<Derived> &tree); 52 ComputeCapacity(int oldCapacity)53 inline static int ComputeCapacity(int oldCapacity) 54 { 55 int capacity = (static_cast<uint32_t>(oldCapacity) << 1) + 1; 56 return (capacity > MIN_CAPACITY) ? capacity : MIN_CAPACITY; 57 } 58 59 static void Remove(const JSThread *thread, const JSHandle<Derived> &tree, int entry); 60 NumberOfElements() const61 inline uint32_t NumberOfElements() const 62 { 63 return Get(NUMBER_OF_ELEMENTS_INDEX).GetInt(); 64 } 65 NumberOfDeletedElements() const66 inline uint32_t NumberOfDeletedElements() const 67 { 68 return Get(NUMBER_OF_HOLE_ENTRIES_INDEX).GetInt(); 69 } 70 Capacity() const71 inline int Capacity() const 72 { 73 return Get(CAPACITY_INDEX).GetInt(); 74 } 75 GetKey(int entry) const76 inline JSTaggedValue GetKey(int entry) const 77 { 78 if (entry < 0) { 79 return JSTaggedValue::Hole(); 80 } 81 int index = EntryToIndex(entry); 82 return GetElement(index); 83 } 84 GetValue(int entry) const85 inline JSTaggedValue GetValue(int entry) const 86 { 87 int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_VALUE_INDEX); 88 return GetElement(index); 89 } 90 GetColor(int entry) const91 inline TreeColor GetColor(int entry) const 92 { 93 if (entry < 0) { 94 return TreeColor::BLACK; 95 } 96 int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_COLOR_INDEX); 97 JSTaggedValue color = GetElement(index); 98 return color.GetInt() == TreeColor::RED ? TreeColor::RED : TreeColor::BLACK; 99 } 100 SetCapacity(const JSThread *thread, int capacity)101 inline void SetCapacity(const JSThread *thread, int capacity) 102 { 103 Set(thread, CAPACITY_INDEX, JSTaggedValue(capacity)); 104 } 105 IsKey(JSTaggedValue key)106 inline static bool IsKey(JSTaggedValue key) 107 { 108 return !key.IsHole(); 109 } 110 SetNumberOfElements(const JSThread *thread, uint32_t num)111 inline void SetNumberOfElements(const JSThread *thread, uint32_t num) 112 { 113 Set(thread, NUMBER_OF_ELEMENTS_INDEX, JSTaggedValue(num)); 114 } 115 SetNumberOfDeletedElements(const JSThread *thread, int num)116 inline void SetNumberOfDeletedElements(const JSThread *thread, int num) 117 { 118 Set(thread, NUMBER_OF_HOLE_ENTRIES_INDEX, JSTaggedValue(num)); 119 } 120 SetRootEntries(const JSThread *thread, int num)121 inline void SetRootEntries(const JSThread *thread, int num) 122 { 123 Set(thread, ROOT_INDEX, JSTaggedValue(num)); 124 } 125 GetRootEntries() const126 inline int GetRootEntries() const 127 { 128 return Get(ROOT_INDEX).GetInt(); 129 } 130 131 static int FindEntry(JSThread *thread, const JSHandle<Derived> &tree, const JSHandle<JSTaggedValue> &key); 132 133 static ComparisonResult EntryCompare(JSThread *thread, const JSHandle<JSTaggedValue> valueX, 134 const JSHandle<JSTaggedValue> valueY, JSHandle<Derived> tree); 135 SetKey(const JSThread *thread, uint32_t entry, JSTaggedValue key)136 inline void SetKey(const JSThread *thread, uint32_t entry, JSTaggedValue key) 137 { 138 int index = EntryToIndex(entry); 139 SetElement(thread, index, key); 140 } 141 SetValue(const JSThread *thread, uint32_t entry, JSTaggedValue value)142 inline void SetValue(const JSThread *thread, uint32_t entry, JSTaggedValue value) 143 { 144 int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_VALUE_INDEX); 145 SetElement(thread, index, value); 146 } 147 SetCompare(const JSThread *thread, JSTaggedValue fn)148 inline void SetCompare(const JSThread *thread, JSTaggedValue fn) 149 { 150 Set(thread, COMPARE_FUNCTION_INDEX, fn); 151 } 152 GetCompare() const153 inline JSTaggedValue GetCompare() const 154 { 155 return Get(COMPARE_FUNCTION_INDEX); 156 } 157 GetMinimum(int entry) const158 inline int GetMinimum(int entry) const 159 { 160 JSTaggedValue child = GetLeftChild(entry); 161 while (!child.IsHole()) { 162 entry = child.GetInt(); 163 child = GetLeftChild(entry); 164 } 165 return entry; 166 } 167 GetMaximum(int entry) const168 inline int GetMaximum(int entry) const 169 { 170 JSTaggedValue child = GetRightChild(entry); 171 while (!child.IsHole()) { 172 entry = child.GetInt(); 173 child = GetRightChild(entry); 174 } 175 return entry; 176 } 177 GetParent(int entry) const178 inline int GetParent(int entry) const 179 { 180 int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_PARENT_INDEX); 181 JSTaggedValue parent = GetElement(index); 182 return parent.GetInt(); 183 } 184 GetLeftChild(int parent) const185 inline JSTaggedValue GetLeftChild(int parent) const 186 { 187 if (parent < 0) { 188 return JSTaggedValue::Hole(); 189 } 190 int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_LEFT_CHILD_INDEX); 191 return Get(index); 192 } 193 GetRightChild(int parent) const194 inline JSTaggedValue GetRightChild(int parent) const 195 { 196 if (parent < 0) { 197 return JSTaggedValue::Hole(); 198 } 199 int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_RIGHT_CHILD_INDEX); 200 return Get(index); 201 } 202 GetLeftChildIndex(int parent) const203 inline int GetLeftChildIndex(int parent) const 204 { 205 if (parent < 0) { 206 return -1; 207 } 208 int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_LEFT_CHILD_INDEX); 209 JSTaggedValue child = Get(index); 210 return child.IsHole() ? -1 : child.GetInt(); 211 } 212 GetRightChildIndex(int parent) const213 inline int GetRightChildIndex(int parent) const 214 { 215 if (parent < 0) { 216 return -1; 217 } 218 int index = static_cast<int>(EntryToIndex(parent) + Derived::ENTRY_RIGHT_CHILD_INDEX); 219 JSTaggedValue child = Get(index); 220 return child.IsHole() ? -1 : child.GetInt(); 221 } 222 223 protected: GetElement(int index) const224 inline JSTaggedValue GetElement(int index) const 225 { 226 ASSERT(index >= 0 && index < static_cast<int>(GetLength())); 227 return Get(index); 228 } 229 230 // get root GetRootKey() const231 inline JSTaggedValue GetRootKey() const 232 { 233 return GetKey(GetRootEntries()); 234 } 235 EntryToIndex(uint32_t entry) const236 inline int EntryToIndex(uint32_t entry) const 237 { 238 return ELEMENTS_START_INDEX + entry * (Derived::ENTRY_SIZE); 239 } 240 SetElement(const JSThread *thread, uint32_t index, JSTaggedValue element)241 inline void SetElement(const JSThread *thread, uint32_t index, JSTaggedValue element) 242 { 243 ASSERT(index >= 0 && index < GetLength()); 244 Set(thread, index, element); 245 } 246 SetParent(const JSThread *thread, int entry, JSTaggedValue value)247 inline void SetParent(const JSThread *thread, int entry, JSTaggedValue value) 248 { 249 if (entry < 0) { 250 return; 251 } 252 int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_PARENT_INDEX); 253 SetElement(thread, index, value); 254 } 255 SetRoot(JSThread *thread, int index, JSTaggedValue key, JSTaggedValue value)256 inline void SetRoot(JSThread *thread, int index, JSTaggedValue key, JSTaggedValue value) 257 { 258 SetKey(thread, 0, key); 259 SetValue(thread, 0, value); 260 SetParent(thread, 0, JSTaggedValue(-1)); 261 SetColor(thread, 0, TreeColor::BLACK); 262 SetRootEntries(thread, index); 263 } 264 SetColor(const JSThread *thread, int entry, TreeColor color)265 inline void SetColor(const JSThread *thread, int entry, TreeColor color) 266 { 267 if (entry >= 0) { 268 int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_COLOR_INDEX); 269 SetElement(thread, index, JSTaggedValue(static_cast<int>(color))); 270 } 271 } 272 InsertLeftEntry(const JSThread *thread, uint32_t parentIndex, uint32_t entry, JSTaggedValue key, JSTaggedValue value)273 inline void InsertLeftEntry(const JSThread *thread, uint32_t parentIndex, uint32_t entry, JSTaggedValue key, 274 JSTaggedValue value) 275 { 276 SetKey(thread, entry, key); 277 SetValue(thread, entry, value); 278 SetColor(thread, entry, TreeColor::RED); 279 SetParent(thread, entry, JSTaggedValue(parentIndex)); 280 SetLeftChild(thread, parentIndex, JSTaggedValue(entry)); 281 } 282 InsertRightEntry(const JSThread *thread, uint32_t parentIndex, uint32_t entry, JSTaggedValue key, JSTaggedValue value)283 inline void InsertRightEntry(const JSThread *thread, uint32_t parentIndex, uint32_t entry, JSTaggedValue key, 284 JSTaggedValue value) 285 { 286 SetKey(thread, entry, key); 287 SetValue(thread, entry, value); 288 SetColor(thread, entry, TreeColor::RED); 289 SetParent(thread, entry, JSTaggedValue(parentIndex)); 290 SetRightChild(thread, parentIndex, JSTaggedValue(entry)); 291 } 292 293 void InsertRebalance(const JSThread *thread, int index); 294 void DeleteRebalance(const JSThread *thread, int index); 295 IsValidIndex(int entry) const296 inline bool IsValidIndex(int entry) const 297 { 298 return entry != GetRootEntries() && !GetKey(entry).IsHole(); 299 } 300 GetLeftBrother(int entry) const301 inline int GetLeftBrother(int entry) const 302 { 303 JSTaggedValue child = GetRightChild(GetParent(entry)); 304 return child.IsHole() ? -1 : child.GetInt(); 305 } 306 GetRightBrother(int entry) const307 inline int GetRightBrother(int entry) const 308 { 309 JSTaggedValue child = GetLeftChild(GetParent(entry)); 310 return child.IsHole() ? -1 : child.GetInt(); 311 } 312 IsLeft(int entry) const313 inline bool IsLeft(int entry) const 314 { 315 JSTaggedValue child = GetLeftChild(GetParent(entry)); 316 return child.IsHole() ? false : (child.GetInt() == entry); 317 } 318 IsRight(int entry) const319 inline bool IsRight(int entry) const 320 { 321 JSTaggedValue child = GetRightChild(GetParent(entry)); 322 return child.IsHole() ? false : (child.GetInt() == entry); 323 } 324 325 int GetPreDecessor(int entry) const; 326 int GetSuccessor(int entry) const; 327 SetLeftChild(const JSThread *thread, uint32_t entry, JSTaggedValue value)328 inline void SetLeftChild(const JSThread *thread, uint32_t entry, JSTaggedValue value) 329 { 330 int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_LEFT_CHILD_INDEX); 331 SetElement(thread, index, value); 332 } SetRightChild(const JSThread *thread, uint32_t entry, JSTaggedValue value)333 inline void SetRightChild(const JSThread *thread, uint32_t entry, JSTaggedValue value) 334 { 335 int index = static_cast<int>(EntryToIndex(entry) + Derived::ENTRY_RIGHT_CHILD_INDEX); 336 SetElement(thread, index, value); 337 } 338 339 void LeftRotate(const JSThread *thread, int index); 340 void RightRotate(const JSThread *thread, int index); 341 342 static JSHandle<Derived> AdjustTaggedTree(const JSThread *thread, const JSHandle<Derived> &tree, int len); OrdinayEntryCompare(JSThread *thread, const JSHandle<JSTaggedValue> valueX, const JSHandle<JSTaggedValue> valueY)343 inline static ComparisonResult OrdinayEntryCompare(JSThread *thread, const JSHandle<JSTaggedValue> valueX, 344 const JSHandle<JSTaggedValue> valueY) 345 { 346 if (valueX->IsString() && valueY->IsString()) { 347 auto xHandle = JSHandle<EcmaString>(valueX); 348 auto yHandle = JSHandle<EcmaString>(valueY); 349 int result = EcmaStringAccessor::Compare(thread->GetEcmaVM(), xHandle, yHandle); 350 if (result < 0) { 351 return ComparisonResult::LESS; 352 } 353 if (result == 0) { 354 return ComparisonResult::EQUAL; 355 } 356 return ComparisonResult::GREAT; 357 } 358 359 if (valueX->IsNumber() && valueY->IsNumber()) { 360 return JSTaggedValue::StrictNumberCompare(valueX->GetNumber(), valueY->GetNumber()); 361 } 362 363 if (valueX->IsNumber() && valueY->IsString()) { 364 return ComparisonResult::LESS; 365 } 366 if (valueX->IsString() && valueY->IsNumber()) { 367 return ComparisonResult::GREAT; 368 } 369 370 JSHandle<JSTaggedValue> xValueHandle(JSTaggedValue::ToString(thread, valueX)); 371 JSHandle<JSTaggedValue> yValueHandle(JSTaggedValue::ToString(thread, valueY)); 372 ASSERT_NO_ABRUPT_COMPLETION(thread); 373 return JSTaggedValue::Compare(thread, xValueHandle, yValueHandle); 374 } 375 CopyEntry(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index)376 inline void CopyEntry(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index) 377 { 378 newTree->SetKey(thread, index, GetKey(parent)); 379 newTree->SetColor(thread, index, GetColor(parent)); 380 } 381 CopyData(const JSThread *thread, int dst, int src)382 inline void CopyData(const JSThread *thread, int dst, int src) 383 { 384 SetKey(thread, dst, GetKey(src)); 385 } CopyAllData(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index)386 inline void CopyAllData(const JSThread *thread, int parent, const JSHandle<Derived> &newTree, int index) 387 { 388 newTree->SetKey(thread, index, GetKey(parent)); 389 newTree->SetValue(thread, index, GetValue(parent)); 390 newTree->SetColor(thread, index, GetColor(parent)); 391 newTree->SetParent(thread, index, JSTaggedValue(GetParent(parent))); 392 newTree->SetRightChild(thread, index, GetRightChild(parent)); 393 newTree->SetLeftChild(thread, index, GetLeftChild(parent)); 394 } 395 RemoveEntry(const JSThread *thread, int index)396 inline void RemoveEntry(const JSThread *thread, int index) 397 { 398 SetKey(thread, index, JSTaggedValue::Hole()); 399 SetParent(thread, index, JSTaggedValue::Hole()); 400 SetLeftChild(thread, index, JSTaggedValue::Hole()); 401 SetRightChild(thread, index, JSTaggedValue::Hole()); 402 } 403 Transform(JSTaggedValue v) const404 inline JSTaggedValue Transform(JSTaggedValue v) const 405 { 406 return v.IsHole() ? JSTaggedValue::Undefined() : v; 407 } 408 409 void Transplant(const JSThread *thread, int dst, int src); 410 411 static JSTaggedValue GetLowerKey(JSThread *thread, const JSHandle<Derived> &tree, 412 const JSHandle<JSTaggedValue> &key); 413 static JSTaggedValue GetHigherKey(JSThread *thread, const JSHandle<Derived> &tree, 414 const JSHandle<JSTaggedValue> &key); 415 static JSHandle<TaggedArray> GetSortArray(const JSThread *thread, const JSHandle<Derived> &tree); 416 static JSHandle<Derived> Shrink(const JSThread *thread, const JSHandle<Derived> &tree); 417 }; 418 419 420 class TaggedTreeMap : public TaggedTree<TaggedTreeMap> { 421 public: 422 using RBTree = TaggedTree<TaggedTreeMap>; Cast(TaggedObject *obj)423 static TaggedTreeMap *Cast(TaggedObject *obj) 424 { 425 return static_cast<TaggedTreeMap *>(obj); 426 } 427 428 static JSTaggedValue Create(const JSThread *thread, int numberOfElements = MIN_CAPACITY); 429 static JSTaggedValue Set(JSThread *thread, JSHandle<TaggedTreeMap> &obj, 430 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value); Get(JSThread *thread, const JSHandle<TaggedTreeMap> &map, const JSHandle<JSTaggedValue> &key)431 inline static JSTaggedValue Get(JSThread *thread, const JSHandle<TaggedTreeMap> &map, 432 const JSHandle<JSTaggedValue> &key) 433 { 434 int index = RBTree::FindEntry(thread, map, key); 435 return index == -1 ? JSTaggedValue::Undefined() : map->GetValue(index); 436 } 437 438 static JSTaggedValue Delete(JSThread *thread, const JSHandle<TaggedTreeMap> &map, int entry); 439 bool HasValue(const JSThread *thread, JSTaggedValue value) const; 440 441 static JSTaggedValue GetLowerKey(JSThread *thread, const JSHandle<TaggedTreeMap> &map, 442 const JSHandle<JSTaggedValue> &key); 443 static JSTaggedValue GetHigherKey(JSThread *thread, const JSHandle<TaggedTreeMap> &map, 444 const JSHandle<JSTaggedValue> &key); 445 GetFirstKey() const446 inline JSTaggedValue GetFirstKey() const 447 { 448 JSTaggedValue key = GetKey(GetMinimum(GetRootEntries())); 449 return Transform(key); 450 } 451 GetLastKey() const452 inline JSTaggedValue GetLastKey() const 453 { 454 JSTaggedValue key = GetKey(GetMaximum(GetRootEntries())); 455 return Transform(key); 456 } 457 458 static JSTaggedValue SetAll(JSThread *thread, JSHandle<TaggedTreeMap> &dst, const JSHandle<TaggedTreeMap> &src); 459 static JSHandle<TaggedArray> GetArrayFromMap(const JSThread *thread, const JSHandle<TaggedTreeMap> &map); 460 static int FindEntry(JSThread *thread, const JSHandle<TaggedTreeMap> &map, const JSHandle<JSTaggedValue> &key); 461 462 static const int ENTRY_SIZE = 6; 463 static const int ENTRY_VALUE_INDEX = 1; 464 static const int ENTRY_COLOR_INDEX = 2; 465 static const int ENTRY_PARENT_INDEX = 3; 466 static const int ENTRY_LEFT_CHILD_INDEX = 4; 467 static const int ENTRY_RIGHT_CHILD_INDEX = 5; 468 DECL_DUMP() 469 CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeMap> &newMap, int index)470 inline void CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeMap> &newMap, int index) 471 { 472 RBTree::CopyEntry(thread, parent, newMap, index); 473 newMap->SetValue(thread, index, GetValue(parent)); 474 } CopyData(const JSThread *thread, int dst, int src)475 inline void CopyData(const JSThread *thread, int dst, int src) 476 { 477 RBTree::CopyData(thread, dst, src); 478 SetValue(thread, dst, GetValue(src)); 479 } 480 RemoveEntry(const JSThread *thread, int index)481 inline void RemoveEntry(const JSThread *thread, int index) 482 { 483 RBTree::RemoveEntry(thread, index); 484 SetValue(thread, index, JSTaggedValue::Hole()); 485 } 486 }; 487 488 class TaggedTreeSet : public TaggedTree<TaggedTreeSet> { 489 public: 490 using RBTree = TaggedTree<TaggedTreeSet>; Cast(TaggedObject *obj)491 static TaggedTreeSet *Cast(TaggedObject *obj) 492 { 493 return static_cast<TaggedTreeSet *>(obj); 494 } 495 496 static JSTaggedValue Create(const JSThread *thread, int numberOfElements = MIN_CAPACITY); 497 static JSTaggedValue Add(JSThread *thread, JSHandle<TaggedTreeSet> &obj, const JSHandle<JSTaggedValue> &value); 498 static JSTaggedValue Delete(JSThread *thread, const JSHandle<TaggedTreeSet> &set, int entry); 499 500 static JSTaggedValue GetLowerKey(JSThread *thread, const JSHandle<TaggedTreeSet> &set, 501 const JSHandle<JSTaggedValue> &key); 502 static JSTaggedValue GetHigherKey(JSThread *thread, const JSHandle<TaggedTreeSet> &set, 503 const JSHandle<JSTaggedValue> &key); 504 GetFirstKey() const505 inline JSTaggedValue GetFirstKey() const 506 { 507 JSTaggedValue key = GetKey(GetMinimum(GetRootEntries())); 508 return Transform(key); 509 } 510 GetLastKey() const511 inline JSTaggedValue GetLastKey() const 512 { 513 JSTaggedValue key = GetKey(GetMaximum(GetRootEntries())); 514 return Transform(key); 515 } 516 517 static JSHandle<TaggedArray> GetArrayFromSet(const JSThread *thread, const JSHandle<TaggedTreeSet> &set); 518 static int FindEntry(JSThread *thread, const JSHandle<TaggedTreeSet> &set, const JSHandle<JSTaggedValue> &key); 519 520 static const int ENTRY_SIZE = 5; 521 static const int ENTRY_VALUE_INDEX = 0; 522 static const int ENTRY_COLOR_INDEX = 1; 523 static const int ENTRY_PARENT_INDEX = 2; 524 static const int ENTRY_LEFT_CHILD_INDEX = 3; 525 static const int ENTRY_RIGHT_CHILD_INDEX = 4; 526 527 DECL_DUMP() 528 CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeSet> &newMap, int index)529 inline void CopyEntry(const JSThread *thread, int parent, const JSHandle<TaggedTreeSet> &newMap, int index) 530 { 531 RBTree::CopyEntry(thread, parent, newMap, index); 532 newMap->SetValue(thread, index, GetValue(parent)); 533 } 534 CopyData(const JSThread *thread, int dst, int src)535 inline void CopyData(const JSThread *thread, int dst, int src) 536 { 537 RBTree::CopyData(thread, dst, src); 538 SetValue(thread, dst, GetValue(src)); 539 } 540 RemoveEntry(const JSThread *thread, int index)541 inline void RemoveEntry(const JSThread *thread, int index) 542 { 543 RBTree::RemoveEntry(thread, index); 544 SetValue(thread, index, JSTaggedValue::Hole()); 545 } 546 }; 547 } // namespace panda::ecmascript 548 #endif // ECMASCRIPT_TAGGED_TREE_H 549