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_MEM_ECMALIST_H 17 #define ECMASCRIPT_MEM_ECMALIST_H 18 19 #include "ecmascript/mem/mem.h" 20 21 namespace panda::ecmascript { 22 // Invoking std::list will cause cross invoking, which is time-consuming. 23 // Therefore, we implement ecma list inside the vm. 24 25 template<class T> 26 class EcmaList { 27 public: EcmaList()28 EcmaList() : first_(nullptr), last_(nullptr) {} 29 EcmaList(T * node)30 explicit EcmaList(T *node) : first_(node), last_(node) 31 { 32 node->LinkPrev(nullptr); 33 node->LinkNext(nullptr); 34 } 35 ~EcmaList() = default; 36 NO_COPY_SEMANTIC(EcmaList); 37 NO_MOVE_SEMANTIC(EcmaList); AddNode(T * node)38 void AddNode(T *node) 39 { 40 ASSERT(node != nullptr); 41 if (LIKELY(first_ != nullptr)) { 42 T *lastNext = last_->GetNext(); 43 node->LinkNext(lastNext); 44 node->LinkPrev(last_); 45 last_->LinkNext(node); 46 if (lastNext) { 47 lastNext->LinkPrev(node); 48 } else { 49 last_ = node; 50 } 51 } else { 52 node->LinkPrev(nullptr); 53 node->LinkNext(nullptr); 54 first_ = last_ = node; 55 } 56 length_++; 57 } 58 AddNodeToFront(T * node)59 void AddNodeToFront(T *node) 60 { 61 ASSERT(node != nullptr); 62 if (LIKELY(last_ != nullptr)) { 63 node->LinkNext(first_); 64 node->LinkPrev(first_->GetPrev()); 65 first_->LinkPrev(node); 66 first_ = node; 67 } else { 68 node->LinkPrev(nullptr); 69 node->LinkNext(nullptr); 70 first_ = last_ = node; 71 } 72 length_++; 73 } 74 PopBack()75 T *PopBack() 76 { 77 T *node = last_; 78 RemoveNode(last_); 79 return node; 80 } 81 RemoveNode(T * node)82 void RemoveNode(T *node) 83 { 84 ASSERT(HasNode(node)); 85 if (last_ == node) { 86 // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) 87 last_ = node->GetPrev(); 88 } 89 if (first_ == node) { 90 // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) 91 first_ = node->GetNext(); 92 } 93 // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) 94 T *next = node->GetNext(); 95 // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) 96 T *prev = node->GetPrev(); 97 if (next != nullptr) { 98 next->LinkPrev(prev); 99 } 100 if (prev != nullptr) { 101 prev->LinkNext(next); 102 } 103 // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) 104 node->LinkPrev(nullptr); 105 // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) 106 node->LinkNext(nullptr); 107 length_--; 108 } 109 HasNode(T * node)110 bool HasNode(T *node) 111 { 112 T *it = first_; 113 while (it != nullptr) { 114 if (it == node) { 115 return true; 116 } 117 it = it->GetNext(); 118 } 119 return false; 120 } 121 GetFirst()122 T *GetFirst() const 123 { 124 return first_; 125 } 126 GetLast()127 T *GetLast() const 128 { 129 return last_; 130 } 131 IsEmpty()132 bool IsEmpty() const 133 { 134 return last_ == nullptr; 135 } 136 Clear()137 void Clear() 138 { 139 first_ = last_ = nullptr; 140 length_ = 0; 141 } 142 GetLength()143 uint32_t GetLength() const 144 { 145 return length_; 146 } 147 148 private: 149 T *first_; 150 T *last_; 151 uint32_t length_{0}; 152 }; 153 } // namespace panda::ecmascript 154 155 #endif // ECMASCRIPT_MEM_ECMALIST_H 156