blob: d0e867957dc010686d529db653aa245bfbafc033 [file] [log] [blame]
Howard Hinnant7a563db2011-09-14 18:33:51 +00001//===-------------------------- debug.cpp ---------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Howard Hinnant5e571422013-08-23 20:10:18 +000010#define _LIBCPP_DEBUG 1
Howard Hinnantabe26282011-09-16 17:29:17 +000011#include "__config"
Howard Hinnant7a563db2011-09-14 18:33:51 +000012#include "__debug"
13#include "functional"
14#include "algorithm"
15#include "__hash_table"
16#include "mutex"
17
18_LIBCPP_BEGIN_NAMESPACE_STD
19
Howard Hinnant83eade62013-03-06 23:30:19 +000020_LIBCPP_FUNC_VIS
Howard Hinnant7a563db2011-09-14 18:33:51 +000021__libcpp_db*
22__get_db()
23{
24 static __libcpp_db db;
25 return &db;
Howard Hinnantc6e54b92012-12-27 18:46:00 +000026}
Howard Hinnant7a563db2011-09-14 18:33:51 +000027
Howard Hinnant83eade62013-03-06 23:30:19 +000028_LIBCPP_FUNC_VIS
Howard Hinnant7a563db2011-09-14 18:33:51 +000029const __libcpp_db*
30__get_const_db()
31{
32 return __get_db();
33}
34
35namespace
36{
37
38typedef mutex mutex_type;
Howard Hinnant7a563db2011-09-14 18:33:51 +000039typedef lock_guard<mutex_type> WLock;
40typedef lock_guard<mutex_type> RLock;
41
42mutex_type&
43mut()
44{
45 static mutex_type m;
46 return m;
47}
48
49} // unnamed namespace
50
51__i_node::~__i_node()
52{
53 if (__next_)
54 {
55 __next_->~__i_node();
56 free(__next_);
57 }
58}
59
60__c_node::~__c_node()
61{
62 free(beg_);
63 if (__next_)
64 {
65 __next_->~__c_node();
66 free(__next_);
67 }
68}
69
70__libcpp_db::__libcpp_db()
71 : __cbeg_(nullptr),
72 __cend_(nullptr),
73 __csz_(0),
74 __ibeg_(nullptr),
75 __iend_(nullptr),
76 __isz_(0)
77{
78}
79
80__libcpp_db::~__libcpp_db()
81{
82 if (__cbeg_)
83 {
84 for (__c_node** p = __cbeg_; p != __cend_; ++p)
85 {
86 if (*p != nullptr)
87 {
88 (*p)->~__c_node();
89 free(*p);
90 }
91 }
92 free(__cbeg_);
93 }
94 if (__ibeg_)
95 {
96 for (__i_node** p = __ibeg_; p != __iend_; ++p)
97 {
98 if (*p != nullptr)
99 {
100 (*p)->~__i_node();
101 free(*p);
102 }
103 }
104 free(__ibeg_);
105 }
106}
107
108void*
109__libcpp_db::__find_c_from_i(void* __i) const
110{
111 RLock _(mut());
112 __i_node* i = __find_iterator(__i);
Howard Hinnant6dcaf3e2013-04-05 17:58:52 +0000113 _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
Howard Hinnant7608b4a2011-09-16 19:52:23 +0000114 return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
Howard Hinnant7a563db2011-09-14 18:33:51 +0000115}
116
117void
118__libcpp_db::__insert_ic(void* __i, const void* __c)
119{
120 WLock _(mut());
Howard Hinnant499cea12013-08-23 17:37:05 +0000121 if (__cbeg_ == __cend_)
122 return;
Howard Hinnantec3773c2011-12-01 20:21:04 +0000123 size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant7a563db2011-09-14 18:33:51 +0000124 __c_node* c = __cbeg_[hc];
Howard Hinnant499cea12013-08-23 17:37:05 +0000125 if (c == nullptr)
126 return;
Howard Hinnant7a563db2011-09-14 18:33:51 +0000127 while (c->__c_ != __c)
128 {
129 c = c->__next_;
Howard Hinnant499cea12013-08-23 17:37:05 +0000130 if (c == nullptr)
131 return;
Howard Hinnant7a563db2011-09-14 18:33:51 +0000132 }
Howard Hinnant499cea12013-08-23 17:37:05 +0000133 __i_node* i = __insert_iterator(__i);
Howard Hinnant7a563db2011-09-14 18:33:51 +0000134 c->__add(i);
135 i->__c_ = c;
136}
137
138__c_node*
139__libcpp_db::__insert_c(void* __c)
140{
141 WLock _(mut());
Howard Hinnantec3773c2011-12-01 20:21:04 +0000142 if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
Howard Hinnant7a563db2011-09-14 18:33:51 +0000143 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000144 size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
Joerg Sonnenberger912438c2013-04-27 19:13:31 +0000145 __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*)));
Howard Hinnant7a563db2011-09-14 18:33:51 +0000146 if (cbeg == nullptr)
Howard Hinnant3882d392012-08-24 22:15:12 +0000147#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant7a563db2011-09-14 18:33:51 +0000148 throw bad_alloc();
Howard Hinnant3882d392012-08-24 22:15:12 +0000149#else
150 abort();
151#endif
Howard Hinnant7a563db2011-09-14 18:33:51 +0000152 for (__c_node** p = __cbeg_; p != __cend_; ++p)
153 {
154 __c_node* q = *p;
155 while (q != nullptr)
156 {
157 size_t h = hash<void*>()(q->__c_) % nc;
158 __c_node* r = q->__next_;
159 q->__next_ = cbeg[h];
160 cbeg[h] = q;
161 q = r;
162 }
163 }
164 free(__cbeg_);
165 __cbeg_ = cbeg;
166 __cend_ = __cbeg_ + nc;
167 }
Howard Hinnantec3773c2011-12-01 20:21:04 +0000168 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant7a563db2011-09-14 18:33:51 +0000169 __c_node* p = __cbeg_[hc];
Joerg Sonnenberger912438c2013-04-27 19:13:31 +0000170 __c_node* r = __cbeg_[hc] =
171 static_cast<__c_node*>(malloc(sizeof(__c_node)));
Howard Hinnant7a563db2011-09-14 18:33:51 +0000172 if (__cbeg_[hc] == nullptr)
Howard Hinnant3882d392012-08-24 22:15:12 +0000173#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant7a563db2011-09-14 18:33:51 +0000174 throw bad_alloc();
Howard Hinnant3882d392012-08-24 22:15:12 +0000175#else
176 abort();
177#endif
Howard Hinnant7a563db2011-09-14 18:33:51 +0000178 r->__c_ = __c;
179 r->__next_ = p;
180 ++__csz_;
181 return r;
182}
183
184void
185__libcpp_db::__erase_i(void* __i)
186{
187 WLock _(mut());
188 if (__ibeg_ != __iend_)
189 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000190 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant7a563db2011-09-14 18:33:51 +0000191 __i_node* p = __ibeg_[hi];
192 if (p != nullptr)
193 {
194 __i_node* q = nullptr;
195 while (p->__i_ != __i)
196 {
197 q = p;
198 p = p->__next_;
199 if (p == nullptr)
200 return;
201 }
202 if (q == nullptr)
203 __ibeg_[hi] = p->__next_;
204 else
205 q->__next_ = p->__next_;
206 __c_node* c = p->__c_;
207 free(p);
208 --__isz_;
209 if (c != nullptr)
210 c->__remove(p);
211 }
212 }
213}
214
215void
216__libcpp_db::__invalidate_all(void* __c)
217{
218 WLock _(mut());
Howard Hinnant499cea12013-08-23 17:37:05 +0000219 if (__cend_ != __cbeg_)
Howard Hinnant7a563db2011-09-14 18:33:51 +0000220 {
Howard Hinnant499cea12013-08-23 17:37:05 +0000221 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
222 __c_node* p = __cbeg_[hc];
223 if (p == nullptr)
224 return;
225 while (p->__c_ != __c)
226 {
227 p = p->__next_;
228 if (p == nullptr)
229 return;
230 }
231 while (p->end_ != p->beg_)
232 {
233 --p->end_;
234 (*p->end_)->__c_ = nullptr;
235 }
Howard Hinnant7a563db2011-09-14 18:33:51 +0000236 }
237}
238
239__c_node*
240__libcpp_db::__find_c_and_lock(void* __c) const
241{
242 mut().lock();
Howard Hinnant499cea12013-08-23 17:37:05 +0000243 if (__cend_ == __cbeg_)
244 {
245 mut().unlock();
246 return nullptr;
247 }
Howard Hinnantec3773c2011-12-01 20:21:04 +0000248 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant7a563db2011-09-14 18:33:51 +0000249 __c_node* p = __cbeg_[hc];
Howard Hinnant499cea12013-08-23 17:37:05 +0000250 if (p == nullptr)
251 {
252 mut().unlock();
253 return nullptr;
254 }
Howard Hinnant7a563db2011-09-14 18:33:51 +0000255 while (p->__c_ != __c)
256 {
257 p = p->__next_;
Howard Hinnant499cea12013-08-23 17:37:05 +0000258 if (p == nullptr)
259 {
260 mut().unlock();
261 return nullptr;
262 }
Howard Hinnant7a563db2011-09-14 18:33:51 +0000263 }
264 return p;
265}
266
Howard Hinnant1c3ec6d2011-09-27 23:55:03 +0000267__c_node*
268__libcpp_db::__find_c(void* __c) const
269{
Howard Hinnantec3773c2011-12-01 20:21:04 +0000270 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant1c3ec6d2011-09-27 23:55:03 +0000271 __c_node* p = __cbeg_[hc];
272 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
273 while (p->__c_ != __c)
274 {
275 p = p->__next_;
276 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
277 }
278 return p;
279}
280
Howard Hinnant7a563db2011-09-14 18:33:51 +0000281void
282__libcpp_db::unlock() const
283{
284 mut().unlock();
285}
286
287void
288__libcpp_db::__erase_c(void* __c)
289{
290 WLock _(mut());
Howard Hinnant499cea12013-08-23 17:37:05 +0000291 if (__cend_ != __cbeg_)
Howard Hinnant7a563db2011-09-14 18:33:51 +0000292 {
Howard Hinnant499cea12013-08-23 17:37:05 +0000293 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
294 __c_node* p = __cbeg_[hc];
295 if (p == nullptr)
296 return;
297 __c_node* q = nullptr;
298 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
299 while (p->__c_ != __c)
300 {
301 q = p;
302 p = p->__next_;
303 if (p == nullptr)
304 return;
305 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
306 }
307 if (q == nullptr)
308 __cbeg_[hc] = p->__next_;
309 else
310 q->__next_ = p->__next_;
311 while (p->end_ != p->beg_)
312 {
313 --p->end_;
314 (*p->end_)->__c_ = nullptr;
315 }
316 free(p->beg_);
317 free(p);
318 --__csz_;
Howard Hinnant7a563db2011-09-14 18:33:51 +0000319 }
Howard Hinnant7a563db2011-09-14 18:33:51 +0000320}
321
322void
323__libcpp_db::__iterator_copy(void* __i, const void* __i0)
324{
325 WLock _(mut());
326 __i_node* i = __find_iterator(__i);
327 __i_node* i0 = __find_iterator(__i0);
328 __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
Howard Hinnant6dcaf3e2013-04-05 17:58:52 +0000329 if (i == nullptr && i0 != nullptr)
Howard Hinnant7a563db2011-09-14 18:33:51 +0000330 i = __insert_iterator(__i);
331 __c_node* c = i != nullptr ? i->__c_ : nullptr;
332 if (c != c0)
333 {
334 if (c != nullptr)
335 c->__remove(i);
336 if (i != nullptr)
337 {
338 i->__c_ = nullptr;
339 if (c0 != nullptr)
340 {
341 i->__c_ = c0;
342 i->__c_->__add(i);
343 }
344 }
345 }
346}
347
348bool
349__libcpp_db::__dereferenceable(const void* __i) const
350{
351 RLock _(mut());
352 __i_node* i = __find_iterator(__i);
353 return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
354}
355
356bool
357__libcpp_db::__decrementable(const void* __i) const
358{
359 RLock _(mut());
360 __i_node* i = __find_iterator(__i);
361 return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
362}
363
364bool
365__libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
366{
367 RLock _(mut());
368 __i_node* i = __find_iterator(__i);
369 return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
370}
371
372bool
373__libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
374{
375 RLock _(mut());
376 __i_node* i = __find_iterator(__i);
377 return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
378}
379
380bool
Howard Hinnant8b00e6c2013-08-02 00:26:35 +0000381__libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
Howard Hinnant7a563db2011-09-14 18:33:51 +0000382{
383 RLock _(mut());
384 __i_node* i = __find_iterator(__i);
385 __i_node* j = __find_iterator(__j);
386 __c_node* ci = i != nullptr ? i->__c_ : nullptr;
387 __c_node* cj = j != nullptr ? j->__c_ : nullptr;
388 return ci != nullptr && ci == cj;
389}
390
391void
392__libcpp_db::swap(void* c1, void* c2)
393{
394 WLock _(mut());
Howard Hinnantec3773c2011-12-01 20:21:04 +0000395 size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant7a563db2011-09-14 18:33:51 +0000396 __c_node* p1 = __cbeg_[hc];
397 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
398 while (p1->__c_ != c1)
399 {
400 p1 = p1->__next_;
401 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
402 }
Howard Hinnantec3773c2011-12-01 20:21:04 +0000403 hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
Howard Hinnant7a563db2011-09-14 18:33:51 +0000404 __c_node* p2 = __cbeg_[hc];
405 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
406 while (p2->__c_ != c2)
407 {
408 p2 = p2->__next_;
409 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
410 }
411 std::swap(p1->beg_, p2->beg_);
412 std::swap(p1->end_, p2->end_);
413 std::swap(p1->cap_, p2->cap_);
414 for (__i_node** p = p1->beg_; p != p1->end_; ++p)
415 (*p)->__c_ = p1;
416 for (__i_node** p = p2->beg_; p != p2->end_; ++p)
417 (*p)->__c_ = p2;
418}
419
Howard Hinnant7608b4a2011-09-16 19:52:23 +0000420void
421__libcpp_db::__insert_i(void* __i)
422{
423 WLock _(mut());
424 __insert_iterator(__i);
425}
426
Howard Hinnant1c3ec6d2011-09-27 23:55:03 +0000427void
428__c_node::__add(__i_node* i)
429{
430 if (end_ == cap_)
431 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000432 size_t nc = 2*static_cast<size_t>(cap_ - beg_);
Howard Hinnant1c3ec6d2011-09-27 23:55:03 +0000433 if (nc == 0)
434 nc = 1;
Joerg Sonnenberger912438c2013-04-27 19:13:31 +0000435 __i_node** beg =
436 static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
Howard Hinnant1c3ec6d2011-09-27 23:55:03 +0000437 if (beg == nullptr)
Howard Hinnant3882d392012-08-24 22:15:12 +0000438#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant1c3ec6d2011-09-27 23:55:03 +0000439 throw bad_alloc();
Howard Hinnant3882d392012-08-24 22:15:12 +0000440#else
441 abort();
442#endif
Howard Hinnant1c3ec6d2011-09-27 23:55:03 +0000443 if (nc > 1)
444 memcpy(beg, beg_, nc/2*sizeof(__i_node*));
445 free(beg_);
446 beg_ = beg;
447 end_ = beg_ + nc/2;
448 cap_ = beg_ + nc;
449 }
450 *end_++ = i;
451}
452
Howard Hinnant7a563db2011-09-14 18:33:51 +0000453// private api
454
455_LIBCPP_HIDDEN
456__i_node*
457__libcpp_db::__insert_iterator(void* __i)
458{
Howard Hinnantec3773c2011-12-01 20:21:04 +0000459 if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
Howard Hinnant7a563db2011-09-14 18:33:51 +0000460 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000461 size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
Joerg Sonnenberger912438c2013-04-27 19:13:31 +0000462 __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*)));
Howard Hinnant7a563db2011-09-14 18:33:51 +0000463 if (ibeg == nullptr)
Howard Hinnant3882d392012-08-24 22:15:12 +0000464#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant7a563db2011-09-14 18:33:51 +0000465 throw bad_alloc();
Howard Hinnant3882d392012-08-24 22:15:12 +0000466#else
467 abort();
468#endif
Howard Hinnant7a563db2011-09-14 18:33:51 +0000469 for (__i_node** p = __ibeg_; p != __iend_; ++p)
470 {
471 __i_node* q = *p;
472 while (q != nullptr)
473 {
474 size_t h = hash<void*>()(q->__i_) % nc;
475 __i_node* r = q->__next_;
476 q->__next_ = ibeg[h];
477 ibeg[h] = q;
478 q = r;
479 }
480 }
481 free(__ibeg_);
482 __ibeg_ = ibeg;
483 __iend_ = __ibeg_ + nc;
484 }
Howard Hinnantec3773c2011-12-01 20:21:04 +0000485 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant7a563db2011-09-14 18:33:51 +0000486 __i_node* p = __ibeg_[hi];
Joerg Sonnenberger912438c2013-04-27 19:13:31 +0000487 __i_node* r = __ibeg_[hi] =
488 static_cast<__i_node*>(malloc(sizeof(__i_node)));
Howard Hinnant7a563db2011-09-14 18:33:51 +0000489 if (r == nullptr)
Howard Hinnant3882d392012-08-24 22:15:12 +0000490#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant7a563db2011-09-14 18:33:51 +0000491 throw bad_alloc();
Howard Hinnant3882d392012-08-24 22:15:12 +0000492#else
493 abort();
494#endif
Howard Hinnant7a563db2011-09-14 18:33:51 +0000495 ::new(r) __i_node(__i, p, nullptr);
496 ++__isz_;
497 return r;
498}
499
500_LIBCPP_HIDDEN
501__i_node*
502__libcpp_db::__find_iterator(const void* __i) const
503{
504 __i_node* r = nullptr;
505 if (__ibeg_ != __iend_)
506 {
Howard Hinnantec3773c2011-12-01 20:21:04 +0000507 size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
Howard Hinnant7a563db2011-09-14 18:33:51 +0000508 for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
509 {
510 if (nd->__i_ == __i)
511 {
512 r = nd;
513 break;
514 }
515 }
516 }
517 return r;
518}
519
520_LIBCPP_HIDDEN
521void
Howard Hinnant7a563db2011-09-14 18:33:51 +0000522__c_node::__remove(__i_node* p)
523{
524 __i_node** r = find(beg_, end_, p);
525 _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
526 if (--end_ != r)
Howard Hinnantec3773c2011-12-01 20:21:04 +0000527 memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
Howard Hinnant7a563db2011-09-14 18:33:51 +0000528}
529
530_LIBCPP_END_NAMESPACE_STD