1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2  * vim: set ts=8 sts=4 et sw=4 tw=99:
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/. */
6 
7 #ifndef jit_InlineList_h
8 #define jit_InlineList_h
9 
10 #include "jsutil.h"
11 
12 namespace js {
13 
14 template <typename T> class InlineForwardList;
15 template <typename T> class InlineForwardListIterator;
16 
17 template <typename T>
18 class InlineForwardListNode
19 {
20   public:
InlineForwardListNode()21     InlineForwardListNode() : next(nullptr)
22     { }
InlineForwardListNode(InlineForwardListNode<T> * n)23     explicit InlineForwardListNode(InlineForwardListNode<T>* n) : next(n)
24     { }
25 
26     InlineForwardListNode(const InlineForwardListNode<T>&) = delete;
27 
28   protected:
29     friend class InlineForwardList<T>;
30     friend class InlineForwardListIterator<T>;
31 
32     InlineForwardListNode<T>* next;
33 };
34 
35 template <typename T>
36 class InlineForwardList : protected InlineForwardListNode<T>
37 {
38     friend class InlineForwardListIterator<T>;
39 
40     typedef InlineForwardListNode<T> Node;
41 
42     Node* tail_;
43 #ifdef DEBUG
44     int modifyCount_;
45 #endif
46 
thisFromConstructor()47     InlineForwardList<T>* thisFromConstructor() {
48         return this;
49     }
50 
51   public:
InlineForwardList()52     InlineForwardList()
53       : tail_(thisFromConstructor())
54     {
55 #ifdef DEBUG
56         modifyCount_ = 0;
57 #endif
58     }
59 
60   public:
61     typedef InlineForwardListIterator<T> iterator;
62 
63   public:
begin()64     iterator begin() const {
65         return iterator(this);
66     }
begin(Node * item)67     iterator begin(Node* item) const {
68         return iterator(this, item);
69     }
end()70     iterator end() const {
71         return iterator(nullptr);
72     }
removeAt(iterator where)73     void removeAt(iterator where) {
74         removeAfter(where.prev, where.iter);
75     }
pushFront(Node * t)76     void pushFront(Node* t) {
77         insertAfter(this, t);
78     }
pushBack(Node * t)79     void pushBack(Node* t) {
80         MOZ_ASSERT(t->next == nullptr);
81 #ifdef DEBUG
82         modifyCount_++;
83 #endif
84         tail_->next = t;
85         tail_ = t;
86     }
popFront()87     T* popFront() {
88         MOZ_ASSERT(!empty());
89         T* result = static_cast<T*>(this->next);
90         removeAfter(this, result);
91         return result;
92     }
back()93     T* back() const {
94         MOZ_ASSERT(!empty());
95         return static_cast<T*>(tail_);
96     }
insertAfter(Node * at,Node * item)97     void insertAfter(Node* at, Node* item) {
98         MOZ_ASSERT(item->next == nullptr);
99 #ifdef DEBUG
100         modifyCount_++;
101 #endif
102         if (at == tail_)
103             tail_ = item;
104         item->next = at->next;
105         at->next = item;
106     }
removeAfter(Node * at,Node * item)107     void removeAfter(Node* at, Node* item) {
108 #ifdef DEBUG
109         modifyCount_++;
110 #endif
111         if (item == tail_)
112             tail_ = at;
113         MOZ_ASSERT(at->next == item);
114         at->next = item->next;
115         item->next = nullptr;
116     }
removeAndIncrement(iterator & where)117     void removeAndIncrement(iterator &where) {
118         // Do not change modifyCount_ here. The iterator can still be used
119         // after calling this method, unlike the other methods that modify
120         // the list.
121         Node* item = where.iter;
122         where.iter = item->next;
123         if (item == tail_)
124             tail_ = where.prev;
125         MOZ_ASSERT(where.prev->next == item);
126         where.prev->next = where.iter;
127         item->next = nullptr;
128     }
splitAfter(Node * at,InlineForwardList<T> * to)129     void splitAfter(Node* at, InlineForwardList<T>* to) {
130         MOZ_ASSERT(to->empty());
131         if (!at)
132             at = this;
133         if (at == tail_)
134             return;
135 #ifdef DEBUG
136         modifyCount_++;
137 #endif
138         to->next = at->next;
139         to->tail_ = tail_;
140         tail_ = at;
141         at->next = nullptr;
142     }
empty()143     bool empty() const {
144         return tail_ == this;
145     }
clear()146     void clear() {
147         this->next = nullptr;
148         tail_ = this;
149 #ifdef DEBUG
150         modifyCount_ = 0;
151 #endif
152     }
153 };
154 
155 template <typename T>
156 class InlineForwardListIterator
157 {
158 private:
159     friend class InlineForwardList<T>;
160 
161     typedef InlineForwardListNode<T> Node;
162 
163     explicit InlineForwardListIterator<T>(const InlineForwardList<T>* owner)
prev(const_cast<Node * > (static_cast<const Node * > (owner)))164       : prev(const_cast<Node*>(static_cast<const Node*>(owner))),
165         iter(owner ? owner->next : nullptr)
166 #ifdef DEBUG
167       , owner_(owner),
168         modifyCount_(owner ? owner->modifyCount_ : 0)
169 #endif
170     { }
171 
172     InlineForwardListIterator<T>(const InlineForwardList<T>* owner, Node* node)
prev(nullptr)173       : prev(nullptr),
174         iter(node)
175 #ifdef DEBUG
176       , owner_(owner),
177         modifyCount_(owner ? owner->modifyCount_ : 0)
178 #endif
179     { }
180 
181 public:
182     InlineForwardListIterator<T> & operator ++() {
183         MOZ_ASSERT(modifyCount_ == owner_->modifyCount_);
184         prev = iter;
185         iter = iter->next;
186         return *this;
187     }
188     InlineForwardListIterator<T> operator ++(int) {
189         InlineForwardListIterator<T> old(*this);
190         operator++();
191         return old;
192     }
193     T * operator*() const {
194         MOZ_ASSERT(modifyCount_ == owner_->modifyCount_);
195         return static_cast<T*>(iter);
196     }
197     T * operator ->() const {
198         MOZ_ASSERT(modifyCount_ == owner_->modifyCount_);
199         return static_cast<T*>(iter);
200     }
201     bool operator !=(const InlineForwardListIterator<T>& where) const {
202         return iter != where.iter;
203     }
204     bool operator ==(const InlineForwardListIterator<T>& where) const {
205         return iter == where.iter;
206     }
207     explicit operator bool() const {
208         return iter != nullptr;
209     }
210 
211 private:
212     Node* prev;
213     Node* iter;
214 
215 #ifdef DEBUG
216     const InlineForwardList<T>* owner_;
217     int modifyCount_;
218 #endif
219 };
220 
221 template <typename T> class InlineList;
222 template <typename T> class InlineListIterator;
223 template <typename T> class InlineListReverseIterator;
224 
225 template <typename T>
226 class InlineListNode : public InlineForwardListNode<T>
227 {
228   public:
InlineListNode()229     InlineListNode() : InlineForwardListNode<T>(nullptr), prev(nullptr)
230     { }
InlineListNode(InlineListNode<T> * n,InlineListNode<T> * p)231     InlineListNode(InlineListNode<T>* n, InlineListNode<T>* p)
232       : InlineForwardListNode<T>(n),
233         prev(p)
234     { }
235 
236     // Move constructor. Nodes may be moved without being removed from their
237     // containing lists. For example, this allows list nodes to be safely
238     // stored in a resizable Vector -- when the Vector resizes, the new storage
239     // is initialized by this move constructor. |other| is a reference to the
240     // old node which the |this| node here is replacing.
InlineListNode(InlineListNode<T> && other)241     InlineListNode(InlineListNode<T>&& other)
242       : InlineForwardListNode<T>(other.next)
243     {
244         InlineListNode<T>* newNext = static_cast<InlineListNode<T>*>(other.next);
245         InlineListNode<T>* newPrev = other.prev;
246         prev = newPrev;
247 
248         // Update the pointers in the adjacent nodes to point to this node's new
249         // location.
250         newNext->prev = this;
251         newPrev->next = this;
252     }
253 
254     InlineListNode(const InlineListNode<T>&) = delete;
255     void operator=(const InlineListNode<T>&) = delete;
256 
257   protected:
258     friend class InlineList<T>;
259     friend class InlineListIterator<T>;
260     friend class InlineListReverseIterator<T>;
261 
262     InlineListNode<T>* prev;
263 };
264 
265 template <typename T>
266 class InlineList : protected InlineListNode<T>
267 {
268     typedef InlineListNode<T> Node;
269 
270   public:
InlineList()271     InlineList() : InlineListNode<T>(this, this)
272     { }
273 
274   public:
275     typedef InlineListIterator<T> iterator;
276     typedef InlineListReverseIterator<T> reverse_iterator;
277 
278   public:
begin()279     iterator begin() const {
280         return iterator(static_cast<Node*>(this->next));
281     }
begin(Node * t)282     iterator begin(Node* t) const {
283         return iterator(t);
284     }
end()285     iterator end() const {
286         return iterator(this);
287     }
rbegin()288     reverse_iterator rbegin() const {
289         return reverse_iterator(this->prev);
290     }
rbegin(Node * t)291     reverse_iterator rbegin(Node* t) const {
292         return reverse_iterator(t);
293     }
rend()294     reverse_iterator rend() const {
295         return reverse_iterator(this);
296     }
pushFront(Node * t)297     void pushFront(Node* t) {
298         insertAfter(this, t);
299     }
pushFrontUnchecked(Node * t)300     void pushFrontUnchecked(Node* t) {
301         insertAfterUnchecked(this, t);
302     }
pushBack(Node * t)303     void pushBack(Node* t) {
304         insertBefore(this, t);
305     }
pushBackUnchecked(Node * t)306     void pushBackUnchecked(Node* t) {
307         insertBeforeUnchecked(this, t);
308     }
popFront()309     T* popFront() {
310         MOZ_ASSERT(!empty());
311         T* t = static_cast<T*>(this->next);
312         remove(t);
313         return t;
314     }
popBack()315     T* popBack() {
316         MOZ_ASSERT(!empty());
317         T* t = static_cast<T*>(this->prev);
318         remove(t);
319         return t;
320     }
peekBack()321     T* peekBack() const {
322         iterator iter = end();
323         iter--;
324         return *iter;
325     }
insertBefore(Node * at,Node * item)326     void insertBefore(Node* at, Node* item) {
327         MOZ_ASSERT(item->prev == nullptr);
328         MOZ_ASSERT(item->next == nullptr);
329         insertBeforeUnchecked(at, item);
330     }
insertBeforeUnchecked(Node * at,Node * item)331     void insertBeforeUnchecked(Node* at, Node* item) {
332         Node* atPrev = at->prev;
333         item->next = at;
334         item->prev = atPrev;
335         atPrev->next = item;
336         at->prev = item;
337     }
insertAfter(Node * at,Node * item)338     void insertAfter(Node* at, Node* item) {
339         MOZ_ASSERT(item->prev == nullptr);
340         MOZ_ASSERT(item->next == nullptr);
341         insertAfterUnchecked(at, item);
342     }
insertAfterUnchecked(Node * at,Node * item)343     void insertAfterUnchecked(Node* at, Node* item) {
344         Node* atNext = static_cast<Node*>(at->next);
345         item->next = atNext;
346         item->prev = at;
347         atNext->prev = item;
348         at->next = item;
349     }
remove(Node * t)350     void remove(Node* t) {
351         Node* tNext = static_cast<Node*>(t->next);
352         Node* tPrev = t->prev;
353         tPrev->next = tNext;
354         tNext->prev = tPrev;
355         t->next = nullptr;
356         t->prev = nullptr;
357     }
358     // Remove |old| from the list and insert |now| in its place.
replace(Node * old,Node * now)359     void replace(Node* old, Node* now) {
360         MOZ_ASSERT(now->next == nullptr && now->prev == nullptr);
361         Node* listNext = static_cast<Node*>(old->next);
362         Node* listPrev = old->prev;
363         listPrev->next = now;
364         listNext->prev = now;
365         now->next = listNext;
366         now->prev = listPrev;
367         old->next = nullptr;
368         old->prev = nullptr;
369     }
clear()370     void clear() {
371         this->next = this->prev = this;
372     }
empty()373     bool empty() const {
374         return begin() == end();
375     }
takeElements(InlineList & l)376     void takeElements(InlineList& l) {
377         MOZ_ASSERT(&l != this, "cannot takeElements from this");
378         Node* lprev = l.prev;
379         static_cast<Node*>(l.next)->prev = this;
380         lprev->next = this->next;
381         static_cast<Node*>(this->next)->prev = l.prev;
382         this->next = l.next;
383         l.clear();
384     }
385 };
386 
387 template <typename T>
388 class InlineListIterator
389 {
390   private:
391     friend class InlineList<T>;
392 
393     typedef InlineListNode<T> Node;
394 
InlineListIterator(const Node * iter)395     explicit InlineListIterator(const Node* iter)
396       : iter(const_cast<Node*>(iter))
397     { }
398 
399   public:
400     InlineListIterator<T> & operator ++() {
401         iter = static_cast<Node*>(iter->next);
402         return *this;
403     }
404     InlineListIterator<T> operator ++(int) {
405         InlineListIterator<T> old(*this);
406         operator++();
407         return old;
408     }
409     InlineListIterator<T> & operator --() {
410         iter = iter->prev;
411         return *this;
412     }
413     InlineListIterator<T> operator --(int) {
414         InlineListIterator<T> old(*this);
415         operator--();
416         return old;
417     }
418     T * operator*() const {
419         return static_cast<T*>(iter);
420     }
421     T * operator ->() const {
422         return static_cast<T*>(iter);
423     }
424     bool operator !=(const InlineListIterator<T>& where) const {
425         return iter != where.iter;
426     }
427     bool operator ==(const InlineListIterator<T>& where) const {
428         return iter == where.iter;
429     }
430 
431   private:
432     Node* iter;
433 };
434 
435 template <typename T>
436 class InlineListReverseIterator
437 {
438   private:
439     friend class InlineList<T>;
440 
441     typedef InlineListNode<T> Node;
442 
InlineListReverseIterator(const Node * iter)443     explicit InlineListReverseIterator(const Node* iter)
444       : iter(const_cast<Node*>(iter))
445     { }
446 
447   public:
448     InlineListReverseIterator<T> & operator ++() {
449         iter = iter->prev;
450         return *this;
451     }
452     InlineListReverseIterator<T> operator ++(int) {
453         InlineListReverseIterator<T> old(*this);
454         operator++();
455         return old;
456     }
457     InlineListReverseIterator<T> & operator --() {
458         iter = static_cast<Node*>(iter->next);
459         return *this;
460     }
461     InlineListReverseIterator<T> operator --(int) {
462         InlineListReverseIterator<T> old(*this);
463         operator--();
464         return old;
465     }
466     T * operator*() {
467         return static_cast<T*>(iter);
468     }
469     T * operator ->() {
470         return static_cast<T*>(iter);
471     }
472     bool operator !=(const InlineListReverseIterator<T>& where) const {
473         return iter != where.iter;
474     }
475     bool operator ==(const InlineListReverseIterator<T>& where) const {
476         return iter == where.iter;
477     }
478 
479   private:
480     Node* iter;
481 };
482 
483 /* This list type is more or less exactly an InlineForwardList without a sentinel
484  * node. It is useful in cases where you are doing algorithms that deal with many
485  * merging singleton lists, rather than often empty ones.
486  */
487 template <typename T> class InlineConcatListIterator;
488 template <typename T>
489 class InlineConcatList
490 {
491   private:
492     typedef InlineConcatList<T> Node;
493 
thisFromConstructor()494     InlineConcatList<T>* thisFromConstructor() {
495         return this;
496     }
497 
498   public:
InlineConcatList()499     InlineConcatList() : next(nullptr), tail(thisFromConstructor())
500     { }
501 
502     typedef InlineConcatListIterator<T> iterator;
503 
begin()504     iterator begin() const {
505         return iterator(this);
506     }
507 
end()508     iterator end() const {
509         return iterator(nullptr);
510     }
511 
append(InlineConcatList<T> * adding)512     void append(InlineConcatList<T>* adding)
513     {
514         MOZ_ASSERT(tail);
515         MOZ_ASSERT(!tail->next);
516         MOZ_ASSERT(adding->tail);
517         MOZ_ASSERT(!adding->tail->next);
518 
519         tail->next = adding;
520         tail = adding->tail;
521         adding->tail = nullptr;
522     }
523 
524   protected:
525     friend class InlineConcatListIterator<T>;
526     Node* next;
527     Node* tail;
528 };
529 
530 template <typename T>
531 class InlineConcatListIterator
532 {
533   private:
534     friend class InlineConcatList<T>;
535 
536     typedef InlineConcatList<T> Node;
537 
InlineConcatListIterator(const Node * iter)538     explicit InlineConcatListIterator(const Node* iter)
539       : iter(const_cast<Node*>(iter))
540     { }
541 
542   public:
543     InlineConcatListIterator<T> & operator ++() {
544         iter = static_cast<Node*>(iter->next);
545         return *this;
546     }
547     InlineConcatListIterator<T> operator ++(int) {
548         InlineConcatListIterator<T> old(*this);
549         operator++();
550         return old;
551     }
552     T * operator*() const {
553         return static_cast<T*>(iter);
554     }
555     T * operator ->() const {
556         return static_cast<T*>(iter);
557     }
558     bool operator !=(const InlineConcatListIterator<T>& where) const {
559         return iter != where.iter;
560     }
561     bool operator ==(const InlineConcatListIterator<T>& where) const {
562         return iter == where.iter;
563     }
564 
565   private:
566     Node* iter;
567 };
568 
569 template <typename T> class InlineSpaghettiStack;
570 template <typename T> class InlineSpaghettiStackNode;
571 template <typename T> class InlineSpaghettiStackIterator;
572 
573 template <typename T>
574 class InlineSpaghettiStackNode : public InlineForwardListNode<T>
575 {
576     typedef InlineForwardListNode<T> Parent;
577 
578   public:
InlineSpaghettiStackNode()579     InlineSpaghettiStackNode() : Parent()
580     { }
581 
InlineSpaghettiStackNode(InlineSpaghettiStackNode<T> * n)582     explicit InlineSpaghettiStackNode(InlineSpaghettiStackNode<T>* n)
583       : Parent(n)
584     { }
585 
586     InlineSpaghettiStackNode(const InlineSpaghettiStackNode<T>&) = delete;
587 
588   protected:
589     friend class InlineSpaghettiStack<T>;
590     friend class InlineSpaghettiStackIterator<T>;
591 };
592 
593 template <typename T>
594 class InlineSpaghettiStack : protected InlineSpaghettiStackNode<T>
595 {
596     friend class InlineSpaghettiStackIterator<T>;
597 
598     typedef InlineSpaghettiStackNode<T> Node;
599 
600   public:
InlineSpaghettiStack()601     InlineSpaghettiStack()
602     { }
603 
604   public:
605     typedef InlineSpaghettiStackIterator<T> iterator;
606 
607   public:
begin()608     iterator begin() const {
609         return iterator(this);
610     }
end()611     iterator end() const {
612         return iterator(nullptr);
613     }
614 
push(Node * t)615     void push(Node* t) {
616         MOZ_ASSERT(t->next == nullptr);
617         t->next = this->next;
618         this->next = t;
619     }
620 
copy(const InlineSpaghettiStack<T> & stack)621     void copy(const InlineSpaghettiStack<T>& stack) {
622         this->next = stack.next;
623     }
624 
empty()625     bool empty() const {
626         return this->next == nullptr;
627     }
628 };
629 
630 template <typename T>
631 class InlineSpaghettiStackIterator
632 {
633   private:
634     friend class InlineSpaghettiStack<T>;
635 
636     typedef InlineSpaghettiStackNode<T> Node;
637 
638     explicit InlineSpaghettiStackIterator<T>(const InlineSpaghettiStack<T>* owner)
639       : iter(owner ? static_cast<Node*>(owner->next) : nullptr)
640     { }
641 
642   public:
643     InlineSpaghettiStackIterator<T> & operator ++() {
644         iter = static_cast<Node*>(iter->next);
645         return *this;
646     }
647     InlineSpaghettiStackIterator<T> operator ++(int) {
648         InlineSpaghettiStackIterator<T> old(*this);
649         operator++();
650         return old;
651     }
652     T* operator*() const {
653         return static_cast<T*>(iter);
654     }
655     T* operator ->() const {
656         return static_cast<T*>(iter);
657     }
658     bool operator !=(const InlineSpaghettiStackIterator<T>& where) const {
659         return iter != where.iter;
660     }
661     bool operator ==(const InlineSpaghettiStackIterator<T>& where) const {
662         return iter == where.iter;
663     }
664 
665   private:
666     Node* iter;
667 };
668 
669 } // namespace js
670 
671 #endif /* jit_InlineList_h */
672