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