Bug 1885489 - Part 5: Add SnapshotIterator::readInt32(). r=iain
[gecko.git] / js / src / jit / InlineList.h
blob44e445872b7aeca5809655457f83786dc901687b
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef jit_InlineList_h
8 #define jit_InlineList_h
10 #include "mozilla/Assertions.h"
12 namespace js {
14 template <typename T>
15 class InlineForwardList;
16 template <typename T>
17 class InlineForwardListIterator;
19 template <typename T>
20 class InlineForwardListNode {
21 public:
22 InlineForwardListNode() : next(nullptr) {}
23 explicit InlineForwardListNode(InlineForwardListNode<T>* n) : next(n) {}
25 InlineForwardListNode(const InlineForwardListNode<T>&) = delete;
27 protected:
28 friend class InlineForwardList<T>;
29 friend class InlineForwardListIterator<T>;
31 InlineForwardListNode<T>* next;
34 template <typename T>
35 class InlineForwardList : protected InlineForwardListNode<T> {
36 friend class InlineForwardListIterator<T>;
38 using Node = InlineForwardListNode<T>;
40 Node* tail_;
41 #ifdef DEBUG
42 int modifyCount_;
43 #endif
45 InlineForwardList<T>* thisFromConstructor() { return this; }
47 public:
48 InlineForwardList() : tail_(thisFromConstructor()) {
49 #ifdef DEBUG
50 modifyCount_ = 0;
51 #endif
54 public:
55 using iterator = InlineForwardListIterator<T>;
57 public:
58 iterator begin() const { return iterator(this); }
59 iterator begin(Node* item) const { return iterator(this, item); }
60 iterator end() const { return iterator(nullptr); }
61 void removeAt(iterator where) { removeAfter(where.prev, where.iter); }
62 void pushFront(Node* t) { insertAfter(this, t); }
63 void pushBack(Node* t) {
64 MOZ_ASSERT(t->next == nullptr);
65 #ifdef DEBUG
66 modifyCount_++;
67 #endif
68 tail_->next = t;
69 tail_ = t;
71 T* popFront() {
72 MOZ_ASSERT(!empty());
73 T* result = static_cast<T*>(this->next);
74 removeAfter(this, result);
75 return result;
77 T* back() const {
78 MOZ_ASSERT(!empty());
79 return static_cast<T*>(tail_);
81 void insertAfter(Node* at, Node* item) {
82 MOZ_ASSERT(item->next == nullptr);
83 #ifdef DEBUG
84 modifyCount_++;
85 #endif
86 if (at == tail_) {
87 tail_ = item;
89 item->next = at->next;
90 at->next = item;
92 void removeAfter(Node* at, Node* item) {
93 #ifdef DEBUG
94 modifyCount_++;
95 #endif
96 if (item == tail_) {
97 tail_ = at;
99 MOZ_ASSERT(at->next == item);
100 at->next = item->next;
101 item->next = nullptr;
103 void removeAndIncrement(iterator& where) {
104 // Do not change modifyCount_ here. The iterator can still be used
105 // after calling this method, unlike the other methods that modify
106 // the list.
107 Node* item = where.iter;
108 where.iter = item->next;
109 if (item == tail_) {
110 tail_ = where.prev;
112 MOZ_ASSERT(where.prev->next == item);
113 where.prev->next = where.iter;
114 item->next = nullptr;
116 void splitAfter(Node* at, InlineForwardList<T>* to) {
117 MOZ_ASSERT(to->empty());
118 if (!at) {
119 at = this;
121 if (at == tail_) {
122 return;
124 #ifdef DEBUG
125 modifyCount_++;
126 #endif
127 to->next = at->next;
128 to->tail_ = tail_;
129 tail_ = at;
130 at->next = nullptr;
132 bool empty() const { return tail_ == this; }
133 void clear() {
134 this->next = nullptr;
135 tail_ = this;
136 #ifdef DEBUG
137 modifyCount_ = 0;
138 #endif
142 template <typename T>
143 class InlineForwardListIterator {
144 private:
145 friend class InlineForwardList<T>;
147 using Node = InlineForwardListNode<T>;
149 explicit InlineForwardListIterator(const InlineForwardList<T>* owner)
150 : prev(const_cast<Node*>(static_cast<const Node*>(owner))),
151 iter(owner ? owner->next : nullptr)
152 #ifdef DEBUG
154 owner_(owner),
155 modifyCount_(owner ? owner->modifyCount_ : 0)
156 #endif
160 InlineForwardListIterator(const InlineForwardList<T>* owner, Node* node)
161 : prev(nullptr),
162 iter(node)
163 #ifdef DEBUG
165 owner_(owner),
166 modifyCount_(owner ? owner->modifyCount_ : 0)
167 #endif
171 public:
172 InlineForwardListIterator<T>& operator++() {
173 MOZ_ASSERT(modifyCount_ == owner_->modifyCount_);
174 prev = iter;
175 iter = iter->next;
176 return *this;
178 InlineForwardListIterator<T> operator++(int) {
179 InlineForwardListIterator<T> old(*this);
180 operator++();
181 return old;
183 T* operator*() const {
184 MOZ_ASSERT(modifyCount_ == owner_->modifyCount_);
185 return static_cast<T*>(iter);
187 T* operator->() const {
188 MOZ_ASSERT(modifyCount_ == owner_->modifyCount_);
189 return static_cast<T*>(iter);
191 bool operator!=(const InlineForwardListIterator<T>& where) const {
192 return iter != where.iter;
194 bool operator==(const InlineForwardListIterator<T>& where) const {
195 return iter == where.iter;
197 explicit operator bool() const { return iter != nullptr; }
199 private:
200 Node* prev;
201 Node* iter;
203 #ifdef DEBUG
204 const InlineForwardList<T>* owner_;
205 int modifyCount_;
206 #endif
209 template <typename T>
210 class InlineList;
211 template <typename T>
212 class InlineListIterator;
213 template <typename T>
214 class InlineListReverseIterator;
216 template <typename T>
217 class InlineListNode : public InlineForwardListNode<T> {
218 public:
219 InlineListNode() : InlineForwardListNode<T>(nullptr), prev(nullptr) {}
220 InlineListNode(InlineListNode<T>* n, InlineListNode<T>* p)
221 : InlineForwardListNode<T>(n), prev(p) {}
223 // Move constructor. Nodes may be moved without being removed from their
224 // containing lists. For example, this allows list nodes to be safely
225 // stored in a resizable Vector -- when the Vector resizes, the new storage
226 // is initialized by this move constructor. |other| is a reference to the
227 // old node which the |this| node here is replacing.
228 InlineListNode(InlineListNode<T>&& other)
229 : InlineForwardListNode<T>(other.next) {
230 InlineListNode<T>* newNext = static_cast<InlineListNode<T>*>(other.next);
231 InlineListNode<T>* newPrev = other.prev;
232 prev = newPrev;
234 // Update the pointers in the adjacent nodes to point to this node's new
235 // location.
236 newNext->prev = this;
237 newPrev->next = this;
240 InlineListNode(const InlineListNode<T>&) = delete;
241 void operator=(const InlineListNode<T>&) = delete;
243 bool isInList() { return prev != nullptr && this->next != nullptr; }
245 protected:
246 friend class InlineList<T>;
247 friend class InlineListIterator<T>;
248 friend class InlineListReverseIterator<T>;
250 InlineListNode<T>* prev;
253 template <typename T>
254 class InlineList : protected InlineListNode<T> {
255 using Node = InlineListNode<T>;
257 public:
258 InlineList() : InlineListNode<T>(this, this) {}
260 public:
261 using iterator = InlineListIterator<T>;
262 using reverse_iterator = InlineListReverseIterator<T>;
264 public:
265 iterator begin() const { return iterator(static_cast<Node*>(this->next)); }
266 iterator begin(Node* t) const { return iterator(t); }
267 iterator end() const { return iterator(this); }
268 reverse_iterator rbegin() const { return reverse_iterator(this->prev); }
269 reverse_iterator rbegin(Node* t) const { return reverse_iterator(t); }
270 reverse_iterator rend() const { return reverse_iterator(this); }
271 void pushFront(Node* t) { insertAfter(this, t); }
272 void pushFrontUnchecked(Node* t) { insertAfterUnchecked(this, t); }
273 void pushBack(Node* t) { insertBefore(this, t); }
274 void pushBackUnchecked(Node* t) { insertBeforeUnchecked(this, t); }
275 T* popFront() {
276 MOZ_ASSERT(!empty());
277 T* t = static_cast<T*>(this->next);
278 remove(t);
279 return t;
281 T* popBack() {
282 MOZ_ASSERT(!empty());
283 T* t = static_cast<T*>(this->prev);
284 remove(t);
285 return t;
287 T* peekBack() const {
288 iterator iter = end();
289 iter--;
290 return *iter;
292 void insertBefore(Node* at, Node* item) {
293 MOZ_ASSERT(item->prev == nullptr);
294 MOZ_ASSERT(item->next == nullptr);
295 insertBeforeUnchecked(at, item);
297 void insertBeforeUnchecked(Node* at, Node* item) {
298 Node* atPrev = at->prev;
299 item->next = at;
300 item->prev = atPrev;
301 atPrev->next = item;
302 at->prev = item;
304 void insertAfter(Node* at, Node* item) {
305 MOZ_ASSERT(item->prev == nullptr);
306 MOZ_ASSERT(item->next == nullptr);
307 insertAfterUnchecked(at, item);
309 void insertAfterUnchecked(Node* at, Node* item) {
310 Node* atNext = static_cast<Node*>(at->next);
311 item->next = atNext;
312 item->prev = at;
313 atNext->prev = item;
314 at->next = item;
316 void remove(Node* t) {
317 Node* tNext = static_cast<Node*>(t->next);
318 Node* tPrev = t->prev;
319 tPrev->next = tNext;
320 tNext->prev = tPrev;
321 t->next = nullptr;
322 t->prev = nullptr;
324 // Remove |old| from the list and insert |now| in its place.
325 void replace(Node* old, Node* now) {
326 MOZ_ASSERT(now->next == nullptr && now->prev == nullptr);
327 Node* listNext = static_cast<Node*>(old->next);
328 Node* listPrev = old->prev;
329 listPrev->next = now;
330 listNext->prev = now;
331 now->next = listNext;
332 now->prev = listPrev;
333 old->next = nullptr;
334 old->prev = nullptr;
336 void clear() { this->next = this->prev = this; }
337 bool empty() const { return begin() == end(); }
338 void takeElements(InlineList& l) {
339 MOZ_ASSERT(&l != this, "cannot takeElements from this");
340 Node* lprev = l.prev;
341 static_cast<Node*>(l.next)->prev = this;
342 lprev->next = this->next;
343 static_cast<Node*>(this->next)->prev = l.prev;
344 this->next = l.next;
345 l.clear();
349 template <typename T>
350 class InlineListIterator {
351 private:
352 friend class InlineList<T>;
354 using Node = InlineListNode<T>;
356 explicit InlineListIterator(const Node* iter)
357 : iter(const_cast<Node*>(iter)) {}
359 public:
360 InlineListIterator<T>& operator++() {
361 iter = static_cast<Node*>(iter->next);
362 return *this;
364 InlineListIterator<T> operator++(int) {
365 InlineListIterator<T> old(*this);
366 operator++();
367 return old;
369 InlineListIterator<T>& operator--() {
370 iter = iter->prev;
371 return *this;
373 InlineListIterator<T> operator--(int) {
374 InlineListIterator<T> old(*this);
375 operator--();
376 return old;
378 T* operator*() const { return static_cast<T*>(iter); }
379 T* operator->() const { return static_cast<T*>(iter); }
380 bool operator!=(const InlineListIterator<T>& where) const {
381 return iter != where.iter;
383 bool operator==(const InlineListIterator<T>& where) const {
384 return iter == where.iter;
387 private:
388 Node* iter;
391 template <typename T>
392 class InlineListReverseIterator {
393 private:
394 friend class InlineList<T>;
396 using Node = InlineListNode<T>;
398 explicit InlineListReverseIterator(const Node* iter)
399 : iter(const_cast<Node*>(iter)) {}
401 public:
402 InlineListReverseIterator<T>& operator++() {
403 iter = iter->prev;
404 return *this;
406 InlineListReverseIterator<T> operator++(int) {
407 InlineListReverseIterator<T> old(*this);
408 operator++();
409 return old;
411 InlineListReverseIterator<T>& operator--() {
412 iter = static_cast<Node*>(iter->next);
413 return *this;
415 InlineListReverseIterator<T> operator--(int) {
416 InlineListReverseIterator<T> old(*this);
417 operator--();
418 return old;
420 T* operator*() { return static_cast<T*>(iter); }
421 T* operator->() { return static_cast<T*>(iter); }
422 bool operator!=(const InlineListReverseIterator<T>& where) const {
423 return iter != where.iter;
425 bool operator==(const InlineListReverseIterator<T>& where) const {
426 return iter == where.iter;
429 private:
430 Node* iter;
433 // This list type is more or less exactly an InlineForwardList without a
434 // sentinel node. It is useful in cases where you are doing algorithms that deal
435 // with many merging singleton lists, rather than often empty ones.
436 template <typename T>
437 class InlineConcatListIterator;
438 template <typename T>
439 class InlineConcatList {
440 private:
441 using Node = InlineConcatList<T>;
443 InlineConcatList<T>* thisFromConstructor() { return this; }
445 public:
446 InlineConcatList() : next(nullptr), tail(thisFromConstructor()) {}
448 using iterator = InlineConcatListIterator<T>;
450 iterator begin() const { return iterator(this); }
452 iterator end() const { return iterator(nullptr); }
454 void append(InlineConcatList<T>* adding) {
455 MOZ_ASSERT(tail);
456 MOZ_ASSERT(!tail->next);
457 MOZ_ASSERT(adding->tail);
458 MOZ_ASSERT(!adding->tail->next);
460 tail->next = adding;
461 tail = adding->tail;
462 adding->tail = nullptr;
465 protected:
466 friend class InlineConcatListIterator<T>;
467 Node* next;
468 Node* tail;
471 template <typename T>
472 class InlineConcatListIterator {
473 private:
474 friend class InlineConcatList<T>;
476 using Node = InlineConcatList<T>;
478 explicit InlineConcatListIterator(const Node* iter)
479 : iter(const_cast<Node*>(iter)) {}
481 public:
482 InlineConcatListIterator<T>& operator++() {
483 iter = static_cast<Node*>(iter->next);
484 return *this;
486 InlineConcatListIterator<T> operator++(int) {
487 InlineConcatListIterator<T> old(*this);
488 operator++();
489 return old;
491 T* operator*() const { return static_cast<T*>(iter); }
492 T* operator->() const { return static_cast<T*>(iter); }
493 bool operator!=(const InlineConcatListIterator<T>& where) const {
494 return iter != where.iter;
496 bool operator==(const InlineConcatListIterator<T>& where) const {
497 return iter == where.iter;
500 private:
501 Node* iter;
504 template <typename T>
505 class InlineSpaghettiStack;
506 template <typename T>
507 class InlineSpaghettiStackNode;
508 template <typename T>
509 class InlineSpaghettiStackIterator;
511 template <typename T>
512 class InlineSpaghettiStackNode : public InlineForwardListNode<T> {
513 using Parent = InlineForwardListNode<T>;
515 public:
516 InlineSpaghettiStackNode() : Parent() {}
518 explicit InlineSpaghettiStackNode(InlineSpaghettiStackNode<T>* n)
519 : Parent(n) {}
521 InlineSpaghettiStackNode(const InlineSpaghettiStackNode<T>&) = delete;
523 protected:
524 friend class InlineSpaghettiStack<T>;
525 friend class InlineSpaghettiStackIterator<T>;
528 template <typename T>
529 class InlineSpaghettiStack : protected InlineSpaghettiStackNode<T> {
530 friend class InlineSpaghettiStackIterator<T>;
532 using Node = InlineSpaghettiStackNode<T>;
534 public:
535 InlineSpaghettiStack() = default;
537 public:
538 using iterator = InlineSpaghettiStackIterator<T>;
540 public:
541 iterator begin() const { return iterator(this); }
542 iterator end() const { return iterator(nullptr); }
544 void push(Node* t) {
545 MOZ_ASSERT(t->next == nullptr);
546 t->next = this->next;
547 this->next = t;
550 void copy(const InlineSpaghettiStack<T>& stack) { this->next = stack.next; }
552 bool empty() const { return this->next == nullptr; }
555 template <typename T>
556 class InlineSpaghettiStackIterator {
557 private:
558 friend class InlineSpaghettiStack<T>;
560 using Node = InlineSpaghettiStackNode<T>;
562 explicit InlineSpaghettiStackIterator(const InlineSpaghettiStack<T>* owner)
563 : iter(owner ? static_cast<Node*>(owner->next) : nullptr) {}
565 public:
566 InlineSpaghettiStackIterator<T>& operator++() {
567 iter = static_cast<Node*>(iter->next);
568 return *this;
570 InlineSpaghettiStackIterator<T> operator++(int) {
571 InlineSpaghettiStackIterator<T> old(*this);
572 operator++();
573 return old;
575 T* operator*() const { return static_cast<T*>(iter); }
576 T* operator->() const { return static_cast<T*>(iter); }
577 bool operator!=(const InlineSpaghettiStackIterator<T>& where) const {
578 return iter != where.iter;
580 bool operator==(const InlineSpaghettiStackIterator<T>& where) const {
581 return iter == where.iter;
584 private:
585 Node* iter;
588 } // namespace js
590 #endif /* jit_InlineList_h */