LCOV - code coverage report
Current view: top level - js/src/ds - InlineTable.h (source / functions) Hit Total Coverage
Test: output.info Lines: 195 200 97.5 %
Date: 2017-07-14 16:53:18 Functions: 135 156 86.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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 ds_InlineTable_h
       8             : #define ds_InlineTable_h
       9             : 
      10             : #include "mozilla/Move.h"
      11             : 
      12             : #include "jsalloc.h"
      13             : 
      14             : #include "js/HashTable.h"
      15             : 
      16             : namespace js {
      17             : 
      18             : namespace detail {
      19             : 
      20             : template <typename InlineEntry,
      21             :           typename Entry,
      22             :           typename Table,
      23             :           typename HashPolicy,
      24             :           typename AllocPolicy,
      25             :           size_t InlineEntries>
      26          23 : class InlineTable
      27             : {
      28             :   private:
      29             :     using TablePtr    = typename Table::Ptr;
      30             :     using TableAddPtr = typename Table::AddPtr;
      31             :     using TableRange  = typename Table::Range;
      32             :     using Lookup      = typename HashPolicy::Lookup;
      33             : 
      34             :     size_t      inlNext_;
      35             :     size_t      inlCount_;
      36             :     InlineEntry inl_[InlineEntries];
      37             :     Table       table_;
      38             : 
      39             : #ifdef DEBUG
      40             :     template <typename Key>
      41      451826 :     static bool keyNonZero(const Key& key) {
      42             :         // Zero as tombstone means zero keys are invalid.
      43      451826 :         return !!key;
      44             :     }
      45             : #endif
      46             : 
      47      406674 :     InlineEntry* inlineStart() {
      48      406674 :         MOZ_ASSERT(!usingTable());
      49      406674 :         return inl_;
      50             :     }
      51             : 
      52       40726 :     const InlineEntry* inlineStart() const {
      53       40726 :         MOZ_ASSERT(!usingTable());
      54       40726 :         return inl_;
      55             :     }
      56             : 
      57      650472 :     InlineEntry* inlineEnd() {
      58      650472 :         MOZ_ASSERT(!usingTable());
      59      650472 :         return inl_ + inlNext_;
      60             :     }
      61             : 
      62       40726 :     const InlineEntry* inlineEnd() const {
      63       40726 :         MOZ_ASSERT(!usingTable());
      64       40726 :         return inl_ + inlNext_;
      65             :     }
      66             : 
      67     1612674 :     bool usingTable() const {
      68     1612674 :         return inlNext_ > InlineEntries;
      69             :     }
      70             : 
      71         516 :     MOZ_MUST_USE bool switchToTable() {
      72         516 :         MOZ_ASSERT(inlNext_ == InlineEntries);
      73             : 
      74         516 :         if (table_.initialized()) {
      75         485 :             table_.clear();
      76             :         } else {
      77          31 :             if (!table_.init(count()))
      78           0 :                 return false;
      79          31 :             MOZ_ASSERT(table_.initialized());
      80             :         }
      81             : 
      82         516 :         InlineEntry* end = inlineEnd();
      83       12900 :         for (InlineEntry* it = inlineStart(); it != end; ++it) {
      84       12384 :             if (it->key && !it->moveTo(table_))
      85           0 :                 return false;
      86             :         }
      87             : 
      88         516 :         inlNext_ = InlineEntries + 1;
      89         516 :         MOZ_ASSERT(table_.count() == inlCount_);
      90         516 :         MOZ_ASSERT(usingTable());
      91         516 :         return true;
      92             :     }
      93             : 
      94             :     MOZ_NEVER_INLINE
      95             :     MOZ_MUST_USE bool switchAndAdd(const InlineEntry& entry) {
      96             :         if (!switchToTable())
      97             :             return false;
      98             : 
      99             :         return entry.putNew(table_);
     100             :     }
     101             : 
     102             :   public:
     103             :     static const size_t SizeOfInlineEntries = sizeof(InlineEntry) * InlineEntries;
     104             : 
     105          88 :     explicit InlineTable(AllocPolicy a = AllocPolicy())
     106             :       : inlNext_(0),
     107             :         inlCount_(0),
     108          88 :         table_(a)
     109          88 :     { }
     110             : 
     111             :     class Ptr
     112             :     {
     113             :         friend class InlineTable;
     114             : 
     115             :       protected:
     116             :         Entry        entry_;
     117             :         TablePtr     tablePtr_;
     118             :         InlineEntry* inlPtr_;
     119             :         bool         isInlinePtr_;
     120             : 
     121       11659 :         explicit Ptr(TablePtr p)
     122       11659 :           : entry_(p.found() ? &*p : nullptr),
     123             :             tablePtr_(p),
     124       11659 :             isInlinePtr_(false)
     125       11659 :         { }
     126             : 
     127      136677 :         explicit Ptr(InlineEntry* inlineEntry)
     128             :           : entry_(inlineEntry),
     129             :             inlPtr_(inlineEntry),
     130      136677 :             isInlinePtr_(true)
     131      136677 :         { }
     132             : 
     133             :         void operator==(const Ptr& other);
     134             : 
     135             :       public:
     136             :         // Leaves Ptr uninitialized.
     137             :         Ptr() {
     138             : #ifdef DEBUG
     139             :             inlPtr_ = (InlineEntry*) 0xbad;
     140             :             isInlinePtr_ = true;
     141             : #endif
     142             :         }
     143             : 
     144             :         // Default copy constructor works for this structure.
     145             : 
     146      244833 :         bool found() const {
     147      244833 :             return isInlinePtr_ ? bool(inlPtr_) : tablePtr_.found();
     148             :         }
     149             : 
     150      148630 :         explicit operator bool() const {
     151      148630 :             return found();
     152             :         }
     153             : 
     154             :         bool operator==(const Ptr& other) const {
     155             :             MOZ_ASSERT(found() && other.found());
     156             :             if (isInlinePtr_ != other.isInlinePtr_)
     157             :                 return false;
     158             :             if (isInlinePtr_)
     159             :                 return inlPtr_ == other.inlPtr_;
     160             :             return tablePtr_ == other.tablePtr_;
     161             :         }
     162             : 
     163             :         bool operator!=(const Ptr& other) const {
     164             :             return !(*this == other);
     165             :         }
     166             : 
     167             :         Entry& operator*() {
     168             :             MOZ_ASSERT(found());
     169             :             return entry_;
     170             :         }
     171             : 
     172       96203 :         Entry* operator->() {
     173       96203 :             MOZ_ASSERT(found());
     174       96203 :             return &entry_;
     175             :         }
     176             :     };
     177             : 
     178             :     class AddPtr
     179             :     {
     180             :         friend class InlineTable;
     181             : 
     182             :       protected:
     183             :         Entry        entry_;
     184             :         TableAddPtr  tableAddPtr_;
     185             :         InlineEntry* inlAddPtr_;
     186             :         bool         isInlinePtr_;
     187             :         // Indicates whether inlAddPtr is a found result or an add pointer.
     188             :         bool         inlPtrFound_;
     189             : 
     190      147324 :         AddPtr(InlineEntry* ptr, bool found)
     191             :           : entry_(ptr),
     192             :             inlAddPtr_(ptr),
     193             :             isInlinePtr_(true),
     194      147324 :             inlPtrFound_(found)
     195      147324 :         {}
     196             : 
     197       21547 :         explicit AddPtr(const TableAddPtr& p)
     198       30632 :           : entry_(p.found() ? &*p : nullptr),
     199             :             tableAddPtr_(p),
     200       30632 :             isInlinePtr_(false)
     201       21547 :         { }
     202             : 
     203             :       public:
     204             :         AddPtr() {}
     205             : 
     206      459383 :         bool found() const {
     207      459383 :             return isInlinePtr_ ? inlPtrFound_ : tableAddPtr_.found();
     208             :         }
     209             : 
     210      303490 :         explicit operator bool() const {
     211      303490 :             return found();
     212             :         }
     213             : 
     214             :         bool operator==(const AddPtr& other) const {
     215             :             MOZ_ASSERT(found() && other.found());
     216             :             if (isInlinePtr_ != other.isInlinePtr_)
     217             :                 return false;
     218             :             if (isInlinePtr_)
     219             :                 return inlAddPtr_ == other.inlAddPtr_;
     220             :             return tableAddPtr_ == other.tableAddPtr_;
     221             :         }
     222             : 
     223             :         bool operator!=(const AddPtr& other) const {
     224             :             return !(*this == other);
     225             :         }
     226             : 
     227             :         Entry& operator*() {
     228             :             MOZ_ASSERT(found());
     229             :             return entry_;
     230             :         }
     231             : 
     232       34252 :         Entry* operator->() {
     233       34252 :             MOZ_ASSERT(found());
     234       34252 :             return &entry_;
     235             :         }
     236             :     };
     237             : 
     238      115006 :     size_t count() const {
     239      115006 :         return usingTable() ? table_.count() : inlCount_;
     240             :     }
     241             : 
     242             :     bool empty() const {
     243             :         return usingTable() ? table_.empty() : !inlCount_;
     244             :     }
     245             : 
     246       42096 :     void clear() {
     247       42096 :         inlNext_ = 0;
     248       42096 :         inlCount_ = 0;
     249       42096 :     }
     250             : 
     251             :     MOZ_ALWAYS_INLINE
     252      148336 :     Ptr lookup(const Lookup& l) {
     253      148336 :         MOZ_ASSERT(keyNonZero(l));
     254             : 
     255      148336 :         if (usingTable())
     256       11659 :             return Ptr(table_.lookup(l));
     257             : 
     258      136677 :         InlineEntry* end = inlineEnd();
     259      509249 :         for (InlineEntry* it = inlineStart(); it != end; ++it) {
     260      460026 :             if (it->key && HashPolicy::match(it->key, l))
     261       87454 :                 return Ptr(it);
     262             :         }
     263             : 
     264       49223 :         return Ptr(nullptr);
     265             :     }
     266             : 
     267             :     MOZ_ALWAYS_INLINE
     268      168871 :     AddPtr lookupForAdd(const Lookup& l) {
     269      168871 :         MOZ_ASSERT(keyNonZero(l));
     270             : 
     271      168871 :         if (usingTable())
     272       21547 :             return AddPtr(table_.lookupForAdd(l));
     273             : 
     274      147324 :         InlineEntry* end = inlineEnd();
     275      745238 :         for (InlineEntry* it = inlineStart(); it != end; ++it) {
     276      623081 :             if (it->key && HashPolicy::match(it->key, l))
     277       25167 :                 return AddPtr(it, true);
     278             :         }
     279             : 
     280             :         // The add pointer that's returned here may indicate the limit entry of
     281             :         // the linear space, in which case the |add| operation will initialize
     282             :         // the table if necessary and add the entry there.
     283      122157 :         return AddPtr(inlineEnd(), false);
     284             :     }
     285             : 
     286             :     template <typename KeyInput,
     287             :               typename... Args>
     288             :     MOZ_ALWAYS_INLINE
     289      134619 :     MOZ_MUST_USE bool add(AddPtr& p, KeyInput&& key, Args&&... args) {
     290      134619 :         MOZ_ASSERT(!p);
     291      134619 :         MOZ_ASSERT(keyNonZero(key));
     292             : 
     293      134619 :         if (p.isInlinePtr_) {
     294      122157 :             InlineEntry* addPtr = p.inlAddPtr_;
     295      122157 :             MOZ_ASSERT(addPtr == inlineEnd());
     296             : 
     297             :             // Switching to table mode before we add this pointer.
     298      122157 :             if (addPtr == inlineStart() + InlineEntries) {
     299         516 :                 if (!switchToTable())
     300           0 :                     return false;
     301             :                 return table_.putNew(mozilla::Forward<KeyInput>(key),
     302         516 :                                      mozilla::Forward<Args>(args)...);
     303             :             }
     304             : 
     305      121641 :             MOZ_ASSERT(!p.found());
     306      121641 :             MOZ_ASSERT(uintptr_t(inlineEnd()) == uintptr_t(p.inlAddPtr_));
     307      121641 :             addPtr->update(mozilla::Forward<KeyInput>(key),
     308             :                            mozilla::Forward<Args>(args)...);
     309      121641 :             ++inlCount_;
     310      121641 :             ++inlNext_;
     311      121641 :             return true;
     312             :         }
     313             : 
     314             :         return table_.add(p.tableAddPtr_,
     315             :                           mozilla::Forward<KeyInput>(key),
     316       12462 :                           mozilla::Forward<Args>(args)...);
     317             :     }
     318             : 
     319         655 :     void remove(Ptr& p) {
     320         655 :         MOZ_ASSERT(p);
     321         655 :         if (p.isInlinePtr_) {
     322         655 :             MOZ_ASSERT(inlCount_ > 0);
     323         655 :             MOZ_ASSERT(p.inlPtr_->key != nullptr);
     324         655 :             p.inlPtr_->key = nullptr;
     325         655 :             --inlCount_;
     326         655 :             return;
     327             :         }
     328           0 :         MOZ_ASSERT(table_.initialized() && usingTable());
     329           0 :         table_.remove(p.tablePtr_);
     330             :     }
     331             : 
     332             :     void remove(const Lookup& l) {
     333             :         if (Ptr p = lookup(l))
     334             :             remove(p);
     335             :     }
     336             : 
     337             :     class Range
     338             :     {
     339             :         friend class InlineTable;
     340             : 
     341             :       protected:
     342             :         TableRange   tableRange_;
     343             :         InlineEntry* cur_;
     344             :         InlineEntry* end_;
     345             :         bool         isInline_;
     346             : 
     347         420 :         explicit Range(TableRange r)
     348             :           : cur_(nullptr),
     349             :             end_(nullptr),
     350         420 :             isInline_(false)
     351             :         {
     352         420 :             tableRange_ = r;
     353         420 :             MOZ_ASSERT(!isInlineRange());
     354         420 :         }
     355             : 
     356       40726 :         Range(const InlineEntry* begin, const InlineEntry* end)
     357             :           : cur_(const_cast<InlineEntry*>(begin)),
     358             :             end_(const_cast<InlineEntry*>(end)),
     359       40726 :             isInline_(true)
     360             :         {
     361       40726 :             advancePastNulls(cur_);
     362       40726 :             MOZ_ASSERT(isInlineRange());
     363       40726 :         }
     364             : 
     365     1065416 :         bool assertInlineRangeInvariants() const {
     366     1065416 :             MOZ_ASSERT(uintptr_t(cur_) <= uintptr_t(end_));
     367     1065416 :             MOZ_ASSERT_IF(cur_ != end_, cur_->key != nullptr);
     368     1065416 :             return true;
     369             :         }
     370             : 
     371     1242320 :         bool isInlineRange() const {
     372     1242320 :             MOZ_ASSERT_IF(isInline_, assertInlineRangeInvariants());
     373     1242320 :             return isInline_;
     374             :         }
     375             : 
     376      130897 :         void advancePastNulls(InlineEntry* begin) {
     377      130897 :             InlineEntry* newCur = begin;
     378      132941 :             while (newCur < end_ && nullptr == newCur->key)
     379        1022 :                 ++newCur;
     380      130897 :             MOZ_ASSERT(uintptr_t(newCur) <= uintptr_t(end_));
     381      130897 :             cur_ = newCur;
     382      130897 :         }
     383             : 
     384       90171 :         void bumpCurPtr() {
     385       90171 :             MOZ_ASSERT(isInlineRange());
     386       90171 :             advancePastNulls(cur_ + 1);
     387       90171 :         }
     388             : 
     389             :       public:
     390      744940 :         bool empty() const {
     391      744940 :             return isInlineRange() ? cur_ == end_ : tableRange_.empty();
     392             :         }
     393             : 
     394      253702 :         Entry front() {
     395      253702 :             MOZ_ASSERT(!empty());
     396      253702 :             if (isInlineRange())
     397      205219 :                 return Entry(cur_);
     398       48483 :             return Entry(&tableRange_.front());
     399             :         }
     400             : 
     401      112361 :         void popFront() {
     402      112361 :             MOZ_ASSERT(!empty());
     403      112361 :             if (isInlineRange())
     404       90171 :                 bumpCurPtr();
     405             :             else
     406       22190 :                 tableRange_.popFront();
     407      112361 :         }
     408             :     };
     409             : 
     410       41146 :     Range all() const {
     411       41146 :         return usingTable() ? Range(table_.all()) : Range(inlineStart(), inlineEnd());
     412             :     }
     413             : };
     414             : 
     415             : } // namespace detail
     416             : 
     417             : // A map with InlineEntries number of entries kept inline in an array.
     418             : //
     419             : // The Key type must be zeroable as zeros are used as tombstone keys.
     420             : // The Value type must have a default constructor.
     421             : //
     422             : // The API is very much like HashMap's.
     423             : template <typename Key,
     424             :           typename Value,
     425             :           size_t InlineEntries,
     426             :           typename HashPolicy = DefaultHasher<Key>,
     427             :           typename AllocPolicy = TempAllocPolicy>
     428          23 : class InlineMap
     429             : {
     430             :     using Map = HashMap<Key, Value, HashPolicy, AllocPolicy>;
     431             : 
     432        2112 :     struct InlineEntry
     433             :     {
     434             :         Key   key;
     435             :         Value value;
     436             : 
     437             :         template <typename KeyInput, typename ValueInput>
     438      121641 :         void update(KeyInput&& key, ValueInput&& value) {
     439      121641 :             this->key = mozilla::Forward<KeyInput>(key);
     440      121641 :             this->value = mozilla::Forward<ValueInput>(value);
     441      121641 :         }
     442             : 
     443       12384 :         MOZ_MUST_USE bool moveTo(Map& map) {
     444       12384 :             return map.putNew(mozilla::Move(key), mozilla::Move(value));
     445             :         }
     446             :     };
     447             : 
     448             :     class Entry
     449             :     {
     450             :         using MapEntry = typename Map::Entry;
     451             : 
     452             :         MapEntry*    mapEntry_;
     453             :         InlineEntry* inlineEntry_;
     454             : 
     455             :       public:
     456             :         Entry() = default;
     457             : 
     458       81689 :         explicit Entry(MapEntry* mapEntry)
     459             :           : mapEntry_(mapEntry),
     460       81689 :             inlineEntry_(nullptr)
     461       81689 :         { }
     462             : 
     463      489255 :         explicit Entry(InlineEntry* inlineEntry)
     464             :           : mapEntry_(nullptr),
     465      489255 :             inlineEntry_(inlineEntry)
     466      489255 :         { }
     467             : 
     468      109970 :         const Key& key() const {
     469      109970 :             MOZ_ASSERT(!!mapEntry_ != !!inlineEntry_);
     470      109970 :             if (mapEntry_)
     471       22064 :                 return mapEntry_->key();
     472       87906 :             return inlineEntry_->key;
     473             :         }
     474             : 
     475      274198 :         Value& value() {
     476      274198 :             MOZ_ASSERT(!!mapEntry_ != !!inlineEntry_);
     477      274198 :             if (mapEntry_)
     478       44983 :                 return mapEntry_->value();
     479      229215 :             return inlineEntry_->value;
     480             :         }
     481             :     };
     482             : 
     483             :     using Impl = detail::InlineTable<InlineEntry, Entry,
     484             :                                      Map, HashPolicy, AllocPolicy,
     485             :                                      InlineEntries>;
     486             : 
     487             :     Impl impl_;
     488             : 
     489             :   public:
     490             :     using Table  = Map;
     491             :     using Ptr    = typename Impl::Ptr;
     492             :     using AddPtr = typename Impl::AddPtr;
     493             :     using Range  = typename Impl::Range;
     494             :     using Lookup = typename HashPolicy::Lookup;
     495             : 
     496             :     static const size_t SizeOfInlineEntries = Impl::SizeOfInlineEntries;
     497             : 
     498          88 :     explicit InlineMap(AllocPolicy a = AllocPolicy())
     499          88 :       : impl_(a)
     500          88 :     { }
     501             : 
     502      114975 :     size_t count() const {
     503      114975 :         return impl_.count();
     504             :     }
     505             : 
     506             :     bool empty() const {
     507             :         return impl_.empty();
     508             :     }
     509             : 
     510       42096 :     void clear() {
     511       42096 :         impl_.clear();
     512       42096 :     }
     513             : 
     514       41146 :     Range all() const {
     515       41146 :         return impl_.all();
     516             :     }
     517             : 
     518             :     MOZ_ALWAYS_INLINE
     519      148336 :     Ptr lookup(const Lookup& l) {
     520      148336 :         return impl_.lookup(l);
     521             :     }
     522             : 
     523             :     MOZ_ALWAYS_INLINE
     524             :     bool has(const Lookup& l) const {
     525             :         return const_cast<InlineMap*>(this)->lookup(l).found();
     526             :     }
     527             : 
     528             :     MOZ_ALWAYS_INLINE
     529      168871 :     AddPtr lookupForAdd(const Lookup& l) {
     530      168871 :         return impl_.lookupForAdd(l);
     531             :     }
     532             : 
     533             :     template <typename KeyInput, typename ValueInput>
     534             :     MOZ_ALWAYS_INLINE
     535      134619 :     MOZ_MUST_USE bool add(AddPtr& p, KeyInput&& key, ValueInput&& value) {
     536      134619 :         return impl_.add(p, mozilla::Forward<KeyInput>(key), mozilla::Forward<ValueInput>(value));
     537             :     }
     538             : 
     539             :     template <typename KeyInput, typename ValueInput>
     540             :     MOZ_MUST_USE bool put(KeyInput&& key, ValueInput&& value) {
     541             :         AddPtr p = lookupForAdd(key);
     542             :         if (p) {
     543             :             p->value() = mozilla::Forward<ValueInput>(value);
     544             :             return true;
     545             :         }
     546             :         return add(p, mozilla::Forward<KeyInput>(key), mozilla::Forward<ValueInput>(value));
     547             :     }
     548             : 
     549         655 :     void remove(Ptr& p) {
     550         655 :         impl_.remove(p);
     551         655 :     }
     552             : 
     553             :     void remove(const Lookup& l) {
     554             :         impl_.remove(l);
     555             :     }
     556             : };
     557             : 
     558             : // A set with InlineEntries number of entries kept inline in an array.
     559             : //
     560             : // The T type must be zeroable as zeros are used as tombstone keys.
     561             : // The T type must have a default constructor.
     562             : //
     563             : // The API is very much like HashMap's.
     564             : template <typename T,
     565             :           size_t InlineEntries,
     566             :           typename HashPolicy = DefaultHasher<T>,
     567             :           typename AllocPolicy = TempAllocPolicy>
     568             : class InlineSet
     569             : {
     570             :     using Set = HashSet<T, HashPolicy, AllocPolicy>;
     571             : 
     572             :     struct InlineEntry
     573             :     {
     574             :         T key;
     575             : 
     576             :         template <typename TInput>
     577             :         void update(TInput&& key) {
     578             :             this->key = mozilla::Forward<TInput>(key);
     579             :         }
     580             : 
     581             :         MOZ_MUST_USE bool moveTo(Set& set) {
     582             :             return set.putNew(mozilla::Move(key));
     583             :         }
     584             :     };
     585             : 
     586             :     class Entry
     587             :     {
     588             :         using SetEntry = typename Set::Entry;
     589             : 
     590             :         SetEntry*    setEntry_;
     591             :         InlineEntry* inlineEntry_;
     592             : 
     593             :       public:
     594             :         Entry() = default;
     595             : 
     596             :         explicit Entry(const SetEntry* setEntry)
     597             :           : setEntry_(const_cast<SetEntry*>(setEntry)),
     598             :             inlineEntry_(nullptr)
     599             :         { }
     600             : 
     601             :         explicit Entry(InlineEntry* inlineEntry)
     602             :           : setEntry_(nullptr),
     603             :             inlineEntry_(inlineEntry)
     604             :         { }
     605             : 
     606             :         operator T() const {
     607             :             MOZ_ASSERT(!!setEntry_ != !!inlineEntry_);
     608             :             if (setEntry_)
     609             :                 return *setEntry_;
     610             :             return inlineEntry_->key;
     611             :         }
     612             :     };
     613             : 
     614             :     using Impl = detail::InlineTable<InlineEntry, Entry,
     615             :                                      Set, HashPolicy, AllocPolicy,
     616             :                                      InlineEntries>;
     617             : 
     618             :     Impl impl_;
     619             : 
     620             :   public:
     621             :     using Table  = Set;
     622             :     using Ptr    = typename Impl::Ptr;
     623             :     using AddPtr = typename Impl::AddPtr;
     624             :     using Range  = typename Impl::Range;
     625             :     using Lookup = typename HashPolicy::Lookup;
     626             : 
     627             :     static const size_t SizeOfInlineEntries = Impl::SizeOfInlineEntries;
     628             : 
     629             :     explicit InlineSet(AllocPolicy a = AllocPolicy())
     630             :       : impl_(a)
     631             :     { }
     632             : 
     633             :     size_t count() const {
     634             :         return impl_.count();
     635             :     }
     636             : 
     637             :     bool empty() const {
     638             :         return impl_.empty();
     639             :     }
     640             : 
     641             :     void clear() {
     642             :         impl_.clear();
     643             :     }
     644             : 
     645             :     Range all() const {
     646             :         return impl_.all();
     647             :     }
     648             : 
     649             :     MOZ_ALWAYS_INLINE
     650             :     Ptr lookup(const Lookup& l) {
     651             :         return impl_.lookup(l);
     652             :     }
     653             : 
     654             :     MOZ_ALWAYS_INLINE
     655             :     bool has(const Lookup& l) const {
     656             :         return const_cast<InlineSet*>(this)->lookup(l).found();
     657             :     }
     658             : 
     659             :     MOZ_ALWAYS_INLINE
     660             :     AddPtr lookupForAdd(const Lookup& l) {
     661             :         return impl_.lookupForAdd(l);
     662             :     }
     663             : 
     664             :     template <typename TInput>
     665             :     MOZ_ALWAYS_INLINE
     666             :     MOZ_MUST_USE bool add(AddPtr& p, TInput&& key) {
     667             :         return impl_.add(p, mozilla::Forward<TInput>(key));
     668             :     }
     669             : 
     670             :     template <typename TInput>
     671             :     MOZ_MUST_USE bool put(TInput&& key) {
     672             :         AddPtr p = lookupForAdd(key);
     673             :         return p ? true : add(p, mozilla::Forward<TInput>(key));
     674             :     }
     675             : 
     676             :     void remove(Ptr& p) {
     677             :         impl_.remove(p);
     678             :     }
     679             : 
     680             :     void remove(const Lookup& l) {
     681             :         impl_.remove(l);
     682             :     }
     683             : };
     684             : 
     685             : } // namespace js
     686             : 
     687             : #endif // ds_InlineTable_h

Generated by: LCOV version 1.13