• 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_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