/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sts=4 et sw=4 tw=99: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jit_InlineList_h #define jit_InlineList_h #include "jsutil.h" namespace js { template class InlineForwardList; template class InlineForwardListIterator; template class InlineForwardListNode { public: InlineForwardListNode() : next(nullptr) { } explicit InlineForwardListNode(InlineForwardListNode* n) : next(n) { } InlineForwardListNode(const InlineForwardListNode&) = delete; protected: friend class InlineForwardList; friend class InlineForwardListIterator; InlineForwardListNode* next; }; template class InlineForwardList : protected InlineForwardListNode { friend class InlineForwardListIterator; typedef InlineForwardListNode Node; Node* tail_; #ifdef DEBUG int modifyCount_; #endif InlineForwardList* thisFromConstructor() { return this; } public: InlineForwardList() : tail_(thisFromConstructor()) { #ifdef DEBUG modifyCount_ = 0; #endif } public: typedef InlineForwardListIterator iterator; public: iterator begin() const { return iterator(this); } iterator begin(Node* item) const { return iterator(this, item); } iterator end() const { return iterator(nullptr); } void removeAt(iterator where) { removeAfter(where.prev, where.iter); } void pushFront(Node* t) { insertAfter(this, t); } void pushBack(Node* t) { MOZ_ASSERT(t->next == nullptr); #ifdef DEBUG modifyCount_++; #endif tail_->next = t; tail_ = t; } T* popFront() { MOZ_ASSERT(!empty()); T* result = static_cast(this->next); removeAfter(this, result); return result; } T* back() const { MOZ_ASSERT(!empty()); return static_cast(tail_); } void insertAfter(Node* at, Node* item) { MOZ_ASSERT(item->next == nullptr); #ifdef DEBUG modifyCount_++; #endif if (at == tail_) tail_ = item; item->next = at->next; at->next = item; } void removeAfter(Node* at, Node* item) { #ifdef DEBUG modifyCount_++; #endif if (item == tail_) tail_ = at; MOZ_ASSERT(at->next == item); at->next = item->next; item->next = nullptr; } void removeAndIncrement(iterator &where) { // Do not change modifyCount_ here. The iterator can still be used // after calling this method, unlike the other methods that modify // the list. Node* item = where.iter; where.iter = item->next; if (item == tail_) tail_ = where.prev; MOZ_ASSERT(where.prev->next == item); where.prev->next = where.iter; item->next = nullptr; } void splitAfter(Node* at, InlineForwardList* to) { MOZ_ASSERT(to->empty()); if (!at) at = this; if (at == tail_) return; #ifdef DEBUG modifyCount_++; #endif to->next = at->next; to->tail_ = tail_; tail_ = at; at->next = nullptr; } bool empty() const { return tail_ == this; } void clear() { this->next = nullptr; tail_ = this; #ifdef DEBUG modifyCount_ = 0; #endif } }; template class InlineForwardListIterator { private: friend class InlineForwardList; typedef InlineForwardListNode Node; explicit InlineForwardListIterator(const InlineForwardList* owner) : prev(const_cast(static_cast(owner))), iter(owner ? owner->next : nullptr) #ifdef DEBUG , owner_(owner), modifyCount_(owner ? owner->modifyCount_ : 0) #endif { } InlineForwardListIterator(const InlineForwardList* owner, Node* node) : prev(nullptr), iter(node) #ifdef DEBUG , owner_(owner), modifyCount_(owner ? owner->modifyCount_ : 0) #endif { } public: InlineForwardListIterator & operator ++() { MOZ_ASSERT(modifyCount_ == owner_->modifyCount_); prev = iter; iter = iter->next; return *this; } InlineForwardListIterator operator ++(int) { InlineForwardListIterator old(*this); operator++(); return old; } T * operator*() const { MOZ_ASSERT(modifyCount_ == owner_->modifyCount_); return static_cast(iter); } T * operator ->() const { MOZ_ASSERT(modifyCount_ == owner_->modifyCount_); return static_cast(iter); } bool operator !=(const InlineForwardListIterator& where) const { return iter != where.iter; } bool operator ==(const InlineForwardListIterator& where) const { return iter == where.iter; } explicit operator bool() const { return iter != nullptr; } private: Node* prev; Node* iter; #ifdef DEBUG const InlineForwardList* owner_; int modifyCount_; #endif }; template class InlineList; template class InlineListIterator; template class InlineListReverseIterator; template class InlineListNode : public InlineForwardListNode { public: InlineListNode() : InlineForwardListNode(nullptr), prev(nullptr) { } InlineListNode(InlineListNode* n, InlineListNode* p) : InlineForwardListNode(n), prev(p) { } // Move constructor. Nodes may be moved without being removed from their // containing lists. For example, this allows list nodes to be safely // stored in a resizable Vector -- when the Vector resizes, the new storage // is initialized by this move constructor. |other| is a reference to the // old node which the |this| node here is replacing. InlineListNode(InlineListNode&& other) : InlineForwardListNode(other.next) { InlineListNode* newNext = static_cast*>(other.next); InlineListNode* newPrev = other.prev; prev = newPrev; // Update the pointers in the adjacent nodes to point to this node's new // location. newNext->prev = this; newPrev->next = this; } InlineListNode(const InlineListNode&) = delete; void operator=(const InlineListNode&) = delete; protected: friend class InlineList; friend class InlineListIterator; friend class InlineListReverseIterator; InlineListNode* prev; }; template class InlineList : protected InlineListNode { typedef InlineListNode Node; public: InlineList() : InlineListNode(this, this) { } public: typedef InlineListIterator iterator; typedef InlineListReverseIterator reverse_iterator; public: iterator begin() const { return iterator(static_cast(this->next)); } iterator begin(Node* t) const { return iterator(t); } iterator end() const { return iterator(this); } reverse_iterator rbegin() const { return reverse_iterator(this->prev); } reverse_iterator rbegin(Node* t) const { return reverse_iterator(t); } reverse_iterator rend() const { return reverse_iterator(this); } void pushFront(Node* t) { insertAfter(this, t); } void pushFrontUnchecked(Node* t) { insertAfterUnchecked(this, t); } void pushBack(Node* t) { insertBefore(this, t); } void pushBackUnchecked(Node* t) { insertBeforeUnchecked(this, t); } T* popFront() { MOZ_ASSERT(!empty()); T* t = static_cast(this->next); remove(t); return t; } T* popBack() { MOZ_ASSERT(!empty()); T* t = static_cast(this->prev); remove(t); return t; } T* peekBack() const { iterator iter = end(); iter--; return *iter; } void insertBefore(Node* at, Node* item) { MOZ_ASSERT(item->prev == nullptr); MOZ_ASSERT(item->next == nullptr); insertBeforeUnchecked(at, item); } void insertBeforeUnchecked(Node* at, Node* item) { Node* atPrev = at->prev; item->next = at; item->prev = atPrev; atPrev->next = item; at->prev = item; } void insertAfter(Node* at, Node* item) { MOZ_ASSERT(item->prev == nullptr); MOZ_ASSERT(item->next == nullptr); insertAfterUnchecked(at, item); } void insertAfterUnchecked(Node* at, Node* item) { Node* atNext = static_cast(at->next); item->next = atNext; item->prev = at; atNext->prev = item; at->next = item; } void remove(Node* t) { Node* tNext = static_cast(t->next); Node* tPrev = t->prev; tPrev->next = tNext; tNext->prev = tPrev; t->next = nullptr; t->prev = nullptr; } // Remove |old| from the list and insert |now| in its place. void replace(Node* old, Node* now) { MOZ_ASSERT(now->next == nullptr && now->prev == nullptr); Node* listNext = static_cast(old->next); Node* listPrev = old->prev; listPrev->next = now; listNext->prev = now; now->next = listNext; now->prev = listPrev; old->next = nullptr; old->prev = nullptr; } void clear() { this->next = this->prev = this; } bool empty() const { return begin() == end(); } void takeElements(InlineList& l) { MOZ_ASSERT(&l != this, "cannot takeElements from this"); Node* lprev = l.prev; static_cast(l.next)->prev = this; lprev->next = this->next; static_cast(this->next)->prev = l.prev; this->next = l.next; l.clear(); } }; template class InlineListIterator { private: friend class InlineList; typedef InlineListNode Node; explicit InlineListIterator(const Node* iter) : iter(const_cast(iter)) { } public: InlineListIterator & operator ++() { iter = static_cast(iter->next); return *this; } InlineListIterator operator ++(int) { InlineListIterator old(*this); operator++(); return old; } InlineListIterator & operator --() { iter = iter->prev; return *this; } InlineListIterator operator --(int) { InlineListIterator old(*this); operator--(); return old; } T * operator*() const { return static_cast(iter); } T * operator ->() const { return static_cast(iter); } bool operator !=(const InlineListIterator& where) const { return iter != where.iter; } bool operator ==(const InlineListIterator& where) const { return iter == where.iter; } private: Node* iter; }; template class InlineListReverseIterator { private: friend class InlineList; typedef InlineListNode Node; explicit InlineListReverseIterator(const Node* iter) : iter(const_cast(iter)) { } public: InlineListReverseIterator & operator ++() { iter = iter->prev; return *this; } InlineListReverseIterator operator ++(int) { InlineListReverseIterator old(*this); operator++(); return old; } InlineListReverseIterator & operator --() { iter = static_cast(iter->next); return *this; } InlineListReverseIterator operator --(int) { InlineListReverseIterator old(*this); operator--(); return old; } T * operator*() { return static_cast(iter); } T * operator ->() { return static_cast(iter); } bool operator !=(const InlineListReverseIterator& where) const { return iter != where.iter; } bool operator ==(const InlineListReverseIterator& where) const { return iter == where.iter; } private: Node* iter; }; /* This list type is more or less exactly an InlineForwardList without a sentinel * node. It is useful in cases where you are doing algorithms that deal with many * merging singleton lists, rather than often empty ones. */ template class InlineConcatListIterator; template class InlineConcatList { private: typedef InlineConcatList Node; InlineConcatList* thisFromConstructor() { return this; } public: InlineConcatList() : next(nullptr), tail(thisFromConstructor()) { } typedef InlineConcatListIterator iterator; iterator begin() const { return iterator(this); } iterator end() const { return iterator(nullptr); } void append(InlineConcatList* adding) { MOZ_ASSERT(tail); MOZ_ASSERT(!tail->next); MOZ_ASSERT(adding->tail); MOZ_ASSERT(!adding->tail->next); tail->next = adding; tail = adding->tail; adding->tail = nullptr; } protected: friend class InlineConcatListIterator; Node* next; Node* tail; }; template class InlineConcatListIterator { private: friend class InlineConcatList; typedef InlineConcatList Node; explicit InlineConcatListIterator(const Node* iter) : iter(const_cast(iter)) { } public: InlineConcatListIterator & operator ++() { iter = static_cast(iter->next); return *this; } InlineConcatListIterator operator ++(int) { InlineConcatListIterator old(*this); operator++(); return old; } T * operator*() const { return static_cast(iter); } T * operator ->() const { return static_cast(iter); } bool operator !=(const InlineConcatListIterator& where) const { return iter != where.iter; } bool operator ==(const InlineConcatListIterator& where) const { return iter == where.iter; } private: Node* iter; }; template class InlineSpaghettiStack; template class InlineSpaghettiStackNode; template class InlineSpaghettiStackIterator; template class InlineSpaghettiStackNode : public InlineForwardListNode { typedef InlineForwardListNode Parent; public: InlineSpaghettiStackNode() : Parent() { } explicit InlineSpaghettiStackNode(InlineSpaghettiStackNode* n) : Parent(n) { } InlineSpaghettiStackNode(const InlineSpaghettiStackNode&) = delete; protected: friend class InlineSpaghettiStack; friend class InlineSpaghettiStackIterator; }; template class InlineSpaghettiStack : protected InlineSpaghettiStackNode { friend class InlineSpaghettiStackIterator; typedef InlineSpaghettiStackNode Node; public: InlineSpaghettiStack() { } public: typedef InlineSpaghettiStackIterator iterator; public: iterator begin() const { return iterator(this); } iterator end() const { return iterator(nullptr); } void push(Node* t) { MOZ_ASSERT(t->next == nullptr); t->next = this->next; this->next = t; } void copy(const InlineSpaghettiStack& stack) { this->next = stack.next; } bool empty() const { return this->next == nullptr; } }; template class InlineSpaghettiStackIterator { private: friend class InlineSpaghettiStack; typedef InlineSpaghettiStackNode Node; explicit InlineSpaghettiStackIterator(const InlineSpaghettiStack* owner) : iter(owner ? static_cast(owner->next) : nullptr) { } public: InlineSpaghettiStackIterator & operator ++() { iter = static_cast(iter->next); return *this; } InlineSpaghettiStackIterator operator ++(int) { InlineSpaghettiStackIterator old(*this); operator++(); return old; } T* operator*() const { return static_cast(iter); } T* operator ->() const { return static_cast(iter); } bool operator !=(const InlineSpaghettiStackIterator& where) const { return iter != where.iter; } bool operator ==(const InlineSpaghettiStackIterator& where) const { return iter == where.iter; } private: Node* iter; }; } // namespace js #endif /* jit_InlineList_h */