xref: /openbsd-src/gnu/llvm/libcxx/src/debug.cpp (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
1*4bdff4beSrobert //===----------------------------------------------------------------------===//
246035553Spatrick //
346035553Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
446035553Spatrick // See https://llvm.org/LICENSE.txt for license information.
546035553Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
646035553Spatrick //
746035553Spatrick //===----------------------------------------------------------------------===//
846035553Spatrick 
9*4bdff4beSrobert #include <__assert>
10*4bdff4beSrobert #include <__config>
11*4bdff4beSrobert #include <__debug>
12*4bdff4beSrobert #include <__hash_table>
13*4bdff4beSrobert #include <algorithm>
14*4bdff4beSrobert #include <cstdio>
15*4bdff4beSrobert #include <functional>
16*4bdff4beSrobert #include <string>
17*4bdff4beSrobert 
1846035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
19*4bdff4beSrobert #  include <mutex>
2046035553Spatrick #  if defined(__ELF__) && defined(_LIBCPP_LINK_PTHREAD_LIB)
2146035553Spatrick #    pragma comment(lib, "pthread")
2246035553Spatrick #  endif
2346035553Spatrick #endif
2446035553Spatrick 
2546035553Spatrick _LIBCPP_BEGIN_NAMESPACE_STD
2646035553Spatrick 
2746035553Spatrick _LIBCPP_FUNC_VIS
2846035553Spatrick __libcpp_db*
__get_db()2946035553Spatrick __get_db()
3046035553Spatrick {
3146035553Spatrick     static _LIBCPP_NO_DESTROY __libcpp_db db;
3246035553Spatrick     return &db;
3346035553Spatrick }
3446035553Spatrick 
3546035553Spatrick _LIBCPP_FUNC_VIS
3646035553Spatrick const __libcpp_db*
__get_const_db()3746035553Spatrick __get_const_db()
3846035553Spatrick {
3946035553Spatrick     return __get_db();
4046035553Spatrick }
4146035553Spatrick 
4246035553Spatrick namespace
4346035553Spatrick {
4446035553Spatrick 
4546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
4646035553Spatrick typedef mutex mutex_type;
4746035553Spatrick typedef lock_guard<mutex_type> WLock;
4846035553Spatrick typedef lock_guard<mutex_type> RLock;
4946035553Spatrick 
5046035553Spatrick mutex_type&
mut()5146035553Spatrick mut()
5246035553Spatrick {
5346035553Spatrick     static _LIBCPP_NO_DESTROY mutex_type m;
5446035553Spatrick     return m;
5546035553Spatrick }
5646035553Spatrick #endif // !_LIBCPP_HAS_NO_THREADS
5746035553Spatrick 
5846035553Spatrick }  // unnamed namespace
5946035553Spatrick 
~__i_node()6046035553Spatrick __i_node::~__i_node()
6146035553Spatrick {
6246035553Spatrick     if (__next_)
6346035553Spatrick     {
6446035553Spatrick         __next_->~__i_node();
6546035553Spatrick         free(__next_);
6646035553Spatrick     }
6746035553Spatrick }
6846035553Spatrick 
~__c_node()6946035553Spatrick __c_node::~__c_node()
7046035553Spatrick {
7146035553Spatrick     free(beg_);
7246035553Spatrick     if (__next_)
7346035553Spatrick     {
7446035553Spatrick         __next_->~__c_node();
7546035553Spatrick         free(__next_);
7646035553Spatrick     }
7746035553Spatrick }
7846035553Spatrick 
__libcpp_db()7946035553Spatrick __libcpp_db::__libcpp_db()
8046035553Spatrick     : __cbeg_(nullptr),
8146035553Spatrick       __cend_(nullptr),
8246035553Spatrick       __csz_(0),
8346035553Spatrick       __ibeg_(nullptr),
8446035553Spatrick       __iend_(nullptr),
8546035553Spatrick       __isz_(0)
8646035553Spatrick {
8746035553Spatrick }
8846035553Spatrick 
~__libcpp_db()8946035553Spatrick __libcpp_db::~__libcpp_db()
9046035553Spatrick {
9146035553Spatrick     if (__cbeg_)
9246035553Spatrick     {
9346035553Spatrick         for (__c_node** p = __cbeg_; p != __cend_; ++p)
9446035553Spatrick         {
9546035553Spatrick             if (*p != nullptr)
9646035553Spatrick             {
9746035553Spatrick                 (*p)->~__c_node();
9846035553Spatrick                 free(*p);
9946035553Spatrick             }
10046035553Spatrick         }
10146035553Spatrick         free(__cbeg_);
10246035553Spatrick     }
10346035553Spatrick     if (__ibeg_)
10446035553Spatrick     {
10546035553Spatrick         for (__i_node** p = __ibeg_; p != __iend_; ++p)
10646035553Spatrick         {
10746035553Spatrick             if (*p != nullptr)
10846035553Spatrick             {
10946035553Spatrick                 (*p)->~__i_node();
11046035553Spatrick                 free(*p);
11146035553Spatrick             }
11246035553Spatrick         }
11346035553Spatrick         free(__ibeg_);
11446035553Spatrick     }
11546035553Spatrick }
11646035553Spatrick 
11746035553Spatrick void*
__find_c_from_i(void * __i) const11846035553Spatrick __libcpp_db::__find_c_from_i(void* __i) const
11946035553Spatrick {
12046035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
12146035553Spatrick     RLock _(mut());
12246035553Spatrick #endif
12346035553Spatrick     __i_node* i = __find_iterator(__i);
12446035553Spatrick     _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
12546035553Spatrick     return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
12646035553Spatrick }
12746035553Spatrick 
12846035553Spatrick void
__insert_ic(void * __i,const void * __c)12946035553Spatrick __libcpp_db::__insert_ic(void* __i, const void* __c)
13046035553Spatrick {
13146035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
13246035553Spatrick     WLock _(mut());
13346035553Spatrick #endif
13446035553Spatrick     if (__cbeg_ == __cend_)
13546035553Spatrick         return;
13646035553Spatrick     size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
13746035553Spatrick     __c_node* c = __cbeg_[hc];
13846035553Spatrick     if (c == nullptr)
13946035553Spatrick         return;
14046035553Spatrick     while (c->__c_ != __c)
14146035553Spatrick     {
14246035553Spatrick         c = c->__next_;
14346035553Spatrick         if (c == nullptr)
14446035553Spatrick             return;
14546035553Spatrick     }
14646035553Spatrick     __i_node* i = __insert_iterator(__i);
14746035553Spatrick     c->__add(i);
14846035553Spatrick     i->__c_ = c;
14946035553Spatrick }
15046035553Spatrick 
15146035553Spatrick void
__insert_c(void * __c,__libcpp_db::_InsertConstruct * __fn)15246035553Spatrick __libcpp_db::__insert_c(void* __c, __libcpp_db::_InsertConstruct *__fn)
15346035553Spatrick {
15446035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
15546035553Spatrick     WLock _(mut());
15646035553Spatrick #endif
15746035553Spatrick     if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
15846035553Spatrick     {
15946035553Spatrick         size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
16046035553Spatrick         __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(__c_node*)));
16146035553Spatrick         if (cbeg == nullptr)
16246035553Spatrick             __throw_bad_alloc();
16346035553Spatrick 
16446035553Spatrick         for (__c_node** p = __cbeg_; p != __cend_; ++p)
16546035553Spatrick         {
16646035553Spatrick             __c_node* q = *p;
16746035553Spatrick             while (q != nullptr)
16846035553Spatrick             {
16946035553Spatrick                 size_t h = hash<void*>()(q->__c_) % nc;
17046035553Spatrick                 __c_node* r = q->__next_;
17146035553Spatrick                 q->__next_ = cbeg[h];
17246035553Spatrick                 cbeg[h] = q;
17346035553Spatrick                 q = r;
17446035553Spatrick             }
17546035553Spatrick         }
17646035553Spatrick         free(__cbeg_);
17746035553Spatrick         __cbeg_ = cbeg;
17846035553Spatrick         __cend_ = __cbeg_ + nc;
17946035553Spatrick     }
18046035553Spatrick     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
18146035553Spatrick     __c_node* p = __cbeg_[hc];
18246035553Spatrick     void *buf = malloc(sizeof(__c_node));
18346035553Spatrick     if (buf == nullptr)
18446035553Spatrick       __throw_bad_alloc();
18546035553Spatrick     __cbeg_[hc] = __fn(buf, __c, p);
18646035553Spatrick 
18746035553Spatrick     ++__csz_;
18846035553Spatrick }
18946035553Spatrick 
19046035553Spatrick void
__erase_i(void * __i)19146035553Spatrick __libcpp_db::__erase_i(void* __i)
19246035553Spatrick {
19346035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
19446035553Spatrick     WLock _(mut());
19546035553Spatrick #endif
19646035553Spatrick     if (__ibeg_ != __iend_)
19746035553Spatrick     {
19846035553Spatrick         size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
19946035553Spatrick         __i_node* p = __ibeg_[hi];
20046035553Spatrick         if (p != nullptr)
20146035553Spatrick         {
20246035553Spatrick             __i_node* q = nullptr;
20346035553Spatrick             while (p->__i_ != __i)
20446035553Spatrick             {
20546035553Spatrick                 q = p;
20646035553Spatrick                 p = p->__next_;
20746035553Spatrick                 if (p == nullptr)
20846035553Spatrick                     return;
20946035553Spatrick             }
21046035553Spatrick             if (q == nullptr)
21146035553Spatrick                 __ibeg_[hi] = p->__next_;
21246035553Spatrick             else
21346035553Spatrick                 q->__next_ = p->__next_;
21446035553Spatrick             __c_node* c = p->__c_;
21546035553Spatrick             --__isz_;
21646035553Spatrick             if (c != nullptr)
21746035553Spatrick                 c->__remove(p);
21846035553Spatrick             free(p);
21946035553Spatrick         }
22046035553Spatrick     }
22146035553Spatrick }
22246035553Spatrick 
22346035553Spatrick void
__invalidate_all(void * __c)22446035553Spatrick __libcpp_db::__invalidate_all(void* __c)
22546035553Spatrick {
22646035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
22746035553Spatrick     WLock _(mut());
22846035553Spatrick #endif
22946035553Spatrick     if (__cend_ != __cbeg_)
23046035553Spatrick     {
23146035553Spatrick         size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
23246035553Spatrick         __c_node* p = __cbeg_[hc];
23346035553Spatrick         if (p == nullptr)
23446035553Spatrick             return;
23546035553Spatrick         while (p->__c_ != __c)
23646035553Spatrick         {
23746035553Spatrick             p = p->__next_;
23846035553Spatrick             if (p == nullptr)
23946035553Spatrick                 return;
24046035553Spatrick         }
24146035553Spatrick         while (p->end_ != p->beg_)
24246035553Spatrick         {
24346035553Spatrick             --p->end_;
24446035553Spatrick             (*p->end_)->__c_ = nullptr;
24546035553Spatrick         }
24646035553Spatrick     }
24746035553Spatrick }
24846035553Spatrick 
24946035553Spatrick __c_node*
__find_c_and_lock(void * __c) const25046035553Spatrick __libcpp_db::__find_c_and_lock(void* __c) const
25146035553Spatrick {
25246035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
25346035553Spatrick     mut().lock();
25446035553Spatrick #endif
25546035553Spatrick     if (__cend_ == __cbeg_)
25646035553Spatrick     {
25746035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
25846035553Spatrick         mut().unlock();
25946035553Spatrick #endif
26046035553Spatrick         return nullptr;
26146035553Spatrick     }
26246035553Spatrick     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
26346035553Spatrick     __c_node* p = __cbeg_[hc];
26446035553Spatrick     if (p == nullptr)
26546035553Spatrick     {
26646035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
26746035553Spatrick         mut().unlock();
26846035553Spatrick #endif
26946035553Spatrick         return nullptr;
27046035553Spatrick     }
27146035553Spatrick     while (p->__c_ != __c)
27246035553Spatrick     {
27346035553Spatrick         p = p->__next_;
27446035553Spatrick         if (p == nullptr)
27546035553Spatrick         {
27646035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
27746035553Spatrick             mut().unlock();
27846035553Spatrick #endif
27946035553Spatrick             return nullptr;
28046035553Spatrick         }
28146035553Spatrick     }
28246035553Spatrick     return p;
28346035553Spatrick }
28446035553Spatrick 
28546035553Spatrick __c_node*
__find_c(void * __c) const28646035553Spatrick __libcpp_db::__find_c(void* __c) const
28746035553Spatrick {
28846035553Spatrick     size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
28946035553Spatrick     __c_node* p = __cbeg_[hc];
29046035553Spatrick     _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
29146035553Spatrick     while (p->__c_ != __c)
29246035553Spatrick     {
29346035553Spatrick         p = p->__next_;
29446035553Spatrick         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
29546035553Spatrick     }
29646035553Spatrick     return p;
29746035553Spatrick }
29846035553Spatrick 
29946035553Spatrick void
unlock() const30046035553Spatrick __libcpp_db::unlock() const
30146035553Spatrick {
30246035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
30346035553Spatrick     mut().unlock();
30446035553Spatrick #endif
30546035553Spatrick }
30646035553Spatrick 
30746035553Spatrick void
__erase_c(void * __c)30846035553Spatrick __libcpp_db::__erase_c(void* __c)
30946035553Spatrick {
31046035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
31146035553Spatrick     WLock _(mut());
31246035553Spatrick #endif
31346035553Spatrick     if (__cend_ != __cbeg_)
31446035553Spatrick     {
31546035553Spatrick         size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
31646035553Spatrick         __c_node* p = __cbeg_[hc];
31746035553Spatrick         if (p == nullptr)
31846035553Spatrick             return;
31946035553Spatrick         __c_node* q = nullptr;
32046035553Spatrick         _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
32146035553Spatrick         while (p->__c_ != __c)
32246035553Spatrick         {
32346035553Spatrick             q = p;
32446035553Spatrick             p = p->__next_;
32546035553Spatrick             if (p == nullptr)
32646035553Spatrick                 return;
32746035553Spatrick             _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
32846035553Spatrick         }
32946035553Spatrick         if (q == nullptr)
33046035553Spatrick             __cbeg_[hc] = p->__next_;
33146035553Spatrick         else
33246035553Spatrick             q->__next_ = p->__next_;
33346035553Spatrick         while (p->end_ != p->beg_)
33446035553Spatrick         {
33546035553Spatrick             --p->end_;
33646035553Spatrick             (*p->end_)->__c_ = nullptr;
33746035553Spatrick         }
33846035553Spatrick         free(p->beg_);
33946035553Spatrick         free(p);
34046035553Spatrick         --__csz_;
34146035553Spatrick     }
34246035553Spatrick }
34346035553Spatrick 
34446035553Spatrick void
__iterator_copy(void * __i,const void * __i0)34546035553Spatrick __libcpp_db::__iterator_copy(void* __i, const void* __i0)
34646035553Spatrick {
34746035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
34846035553Spatrick     WLock _(mut());
34946035553Spatrick #endif
35046035553Spatrick     __i_node* i = __find_iterator(__i);
35146035553Spatrick     __i_node* i0 = __find_iterator(__i0);
35246035553Spatrick     __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
35346035553Spatrick     if (i == nullptr && i0 != nullptr)
35446035553Spatrick         i = __insert_iterator(__i);
35546035553Spatrick     __c_node* c = i != nullptr ? i->__c_ : nullptr;
35646035553Spatrick     if (c != c0)
35746035553Spatrick     {
35846035553Spatrick         if (c != nullptr)
35946035553Spatrick             c->__remove(i);
36046035553Spatrick         if (i != nullptr)
36146035553Spatrick         {
36246035553Spatrick             i->__c_ = nullptr;
36346035553Spatrick             if (c0 != nullptr)
36446035553Spatrick             {
36546035553Spatrick                 i->__c_ = c0;
36646035553Spatrick                 i->__c_->__add(i);
36746035553Spatrick             }
36846035553Spatrick         }
36946035553Spatrick     }
37046035553Spatrick }
37146035553Spatrick 
37246035553Spatrick bool
__dereferenceable(const void * __i) const37346035553Spatrick __libcpp_db::__dereferenceable(const void* __i) const
37446035553Spatrick {
37546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
37646035553Spatrick     RLock _(mut());
37746035553Spatrick #endif
37846035553Spatrick     __i_node* i = __find_iterator(__i);
37946035553Spatrick     return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
38046035553Spatrick }
38146035553Spatrick 
38246035553Spatrick bool
__decrementable(const void * __i) const38346035553Spatrick __libcpp_db::__decrementable(const void* __i) const
38446035553Spatrick {
38546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
38646035553Spatrick     RLock _(mut());
38746035553Spatrick #endif
38846035553Spatrick     __i_node* i = __find_iterator(__i);
38946035553Spatrick     return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
39046035553Spatrick }
39146035553Spatrick 
39246035553Spatrick bool
__addable(const void * __i,ptrdiff_t __n) const39346035553Spatrick __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
39446035553Spatrick {
39546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
39646035553Spatrick     RLock _(mut());
39746035553Spatrick #endif
39846035553Spatrick     __i_node* i = __find_iterator(__i);
39946035553Spatrick     return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
40046035553Spatrick }
40146035553Spatrick 
40246035553Spatrick bool
__subscriptable(const void * __i,ptrdiff_t __n) const40346035553Spatrick __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
40446035553Spatrick {
40546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
40646035553Spatrick     RLock _(mut());
40746035553Spatrick #endif
40846035553Spatrick     __i_node* i = __find_iterator(__i);
40946035553Spatrick     return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
41046035553Spatrick }
41146035553Spatrick 
41246035553Spatrick bool
__less_than_comparable(const void * __i,const void * __j) const41346035553Spatrick __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
41446035553Spatrick {
41546035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
41646035553Spatrick     RLock _(mut());
41746035553Spatrick #endif
41846035553Spatrick     __i_node* i = __find_iterator(__i);
41946035553Spatrick     __i_node* j = __find_iterator(__j);
42046035553Spatrick     __c_node* ci = i != nullptr ? i->__c_ : nullptr;
42146035553Spatrick     __c_node* cj = j != nullptr ? j->__c_ : nullptr;
42276d0caaeSpatrick     return ci == cj;
42346035553Spatrick }
42446035553Spatrick 
42546035553Spatrick void
swap(void * c1,void * c2)42646035553Spatrick __libcpp_db::swap(void* c1, void* c2)
42746035553Spatrick {
42846035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
42946035553Spatrick     WLock _(mut());
43046035553Spatrick #endif
43146035553Spatrick     size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
43246035553Spatrick     __c_node* p1 = __cbeg_[hc];
43346035553Spatrick     _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
43446035553Spatrick     while (p1->__c_ != c1)
43546035553Spatrick     {
43646035553Spatrick         p1 = p1->__next_;
43746035553Spatrick         _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
43846035553Spatrick     }
43946035553Spatrick     hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
44046035553Spatrick     __c_node* p2 = __cbeg_[hc];
44146035553Spatrick     _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
44246035553Spatrick     while (p2->__c_ != c2)
44346035553Spatrick     {
44446035553Spatrick         p2 = p2->__next_;
44546035553Spatrick         _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
44646035553Spatrick     }
44746035553Spatrick     std::swap(p1->beg_, p2->beg_);
44846035553Spatrick     std::swap(p1->end_, p2->end_);
44946035553Spatrick     std::swap(p1->cap_, p2->cap_);
45046035553Spatrick     for (__i_node** p = p1->beg_; p != p1->end_; ++p)
45146035553Spatrick         (*p)->__c_ = p1;
45246035553Spatrick     for (__i_node** p = p2->beg_; p != p2->end_; ++p)
45346035553Spatrick         (*p)->__c_ = p2;
45446035553Spatrick }
45546035553Spatrick 
45646035553Spatrick void
__insert_i(void * __i)45746035553Spatrick __libcpp_db::__insert_i(void* __i)
45846035553Spatrick {
45946035553Spatrick #ifndef _LIBCPP_HAS_NO_THREADS
46046035553Spatrick     WLock _(mut());
46146035553Spatrick #endif
46246035553Spatrick     __insert_iterator(__i);
46346035553Spatrick }
46446035553Spatrick 
46546035553Spatrick void
__add(__i_node * i)46646035553Spatrick __c_node::__add(__i_node* i)
46746035553Spatrick {
46846035553Spatrick     if (end_ == cap_)
46946035553Spatrick     {
47046035553Spatrick         size_t nc = 2*static_cast<size_t>(cap_ - beg_);
47146035553Spatrick         if (nc == 0)
47246035553Spatrick             nc = 1;
47346035553Spatrick         __i_node** beg =
47446035553Spatrick            static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
47546035553Spatrick         if (beg == nullptr)
47646035553Spatrick             __throw_bad_alloc();
47746035553Spatrick 
47846035553Spatrick         if (nc > 1)
47946035553Spatrick             memcpy(beg, beg_, nc/2*sizeof(__i_node*));
48046035553Spatrick         free(beg_);
48146035553Spatrick         beg_ = beg;
48246035553Spatrick         end_ = beg_ + nc/2;
48346035553Spatrick         cap_ = beg_ + nc;
48446035553Spatrick     }
48546035553Spatrick     *end_++ = i;
48646035553Spatrick }
48746035553Spatrick 
48846035553Spatrick // private api
48946035553Spatrick 
49046035553Spatrick _LIBCPP_HIDDEN
49146035553Spatrick __i_node*
__insert_iterator(void * __i)49246035553Spatrick __libcpp_db::__insert_iterator(void* __i)
49346035553Spatrick {
49446035553Spatrick     if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
49546035553Spatrick     {
49646035553Spatrick         size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
49746035553Spatrick         __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(__i_node*)));
49846035553Spatrick         if (ibeg == nullptr)
49946035553Spatrick             __throw_bad_alloc();
50046035553Spatrick 
50146035553Spatrick         for (__i_node** p = __ibeg_; p != __iend_; ++p)
50246035553Spatrick         {
50346035553Spatrick             __i_node* q = *p;
50446035553Spatrick             while (q != nullptr)
50546035553Spatrick             {
50646035553Spatrick                 size_t h = hash<void*>()(q->__i_) % nc;
50746035553Spatrick                 __i_node* r = q->__next_;
50846035553Spatrick                 q->__next_ = ibeg[h];
50946035553Spatrick                 ibeg[h] = q;
51046035553Spatrick                 q = r;
51146035553Spatrick             }
51246035553Spatrick         }
51346035553Spatrick         free(__ibeg_);
51446035553Spatrick         __ibeg_ = ibeg;
51546035553Spatrick         __iend_ = __ibeg_ + nc;
51646035553Spatrick     }
51746035553Spatrick     size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
51846035553Spatrick     __i_node* p = __ibeg_[hi];
51946035553Spatrick     __i_node* r = __ibeg_[hi] =
52046035553Spatrick       static_cast<__i_node*>(malloc(sizeof(__i_node)));
52146035553Spatrick     if (r == nullptr)
52246035553Spatrick         __throw_bad_alloc();
52346035553Spatrick 
52446035553Spatrick     ::new(r) __i_node(__i, p, nullptr);
52546035553Spatrick     ++__isz_;
52646035553Spatrick     return r;
52746035553Spatrick }
52846035553Spatrick 
52946035553Spatrick _LIBCPP_HIDDEN
53046035553Spatrick __i_node*
__find_iterator(const void * __i) const53146035553Spatrick __libcpp_db::__find_iterator(const void* __i) const
53246035553Spatrick {
53346035553Spatrick     __i_node* r = nullptr;
53446035553Spatrick     if (__ibeg_ != __iend_)
53546035553Spatrick     {
53646035553Spatrick         size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
53746035553Spatrick         for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
53846035553Spatrick         {
53946035553Spatrick             if (nd->__i_ == __i)
54046035553Spatrick             {
54146035553Spatrick                 r = nd;
54246035553Spatrick                 break;
54346035553Spatrick             }
54446035553Spatrick         }
54546035553Spatrick     }
54646035553Spatrick     return r;
54746035553Spatrick }
54846035553Spatrick 
54946035553Spatrick _LIBCPP_HIDDEN
55046035553Spatrick void
__remove(__i_node * p)55146035553Spatrick __c_node::__remove(__i_node* p)
55246035553Spatrick {
55346035553Spatrick     __i_node** r = find(beg_, end_, p);
55446035553Spatrick     _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
55546035553Spatrick     if (--end_ != r)
55646035553Spatrick         memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
55746035553Spatrick }
55846035553Spatrick 
55946035553Spatrick _LIBCPP_END_NAMESPACE_STD
560