debug.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. //===-------------------------- 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. #include "__config"
  10. #if !defined(_LIBCPP_SGX_CONFIG)
  11. #define _LIBCPP_DEBUG 1
  12. #include "__config"
  13. #include "__debug"
  14. #include "functional"
  15. #include "algorithm"
  16. #include "__hash_table"
  17. #include "mutex"
  18. _LIBCPP_BEGIN_NAMESPACE_STD
  19. _LIBCPP_FUNC_VIS
  20. __libcpp_db*
  21. __get_db()
  22. {
  23. static __libcpp_db db;
  24. return &db;
  25. }
  26. _LIBCPP_FUNC_VIS
  27. const __libcpp_db*
  28. __get_const_db()
  29. {
  30. return __get_db();
  31. }
  32. namespace
  33. {
  34. #ifndef _LIBCPP_HAS_NO_THREADS
  35. typedef mutex mutex_type;
  36. typedef lock_guard<mutex_type> WLock;
  37. typedef lock_guard<mutex_type> RLock;
  38. mutex_type&
  39. mut()
  40. {
  41. static mutex_type m;
  42. return m;
  43. }
  44. #endif // !_LIBCPP_HAS_NO_THREADS
  45. } // unnamed namespace
  46. __i_node::~__i_node()
  47. {
  48. if (__next_)
  49. {
  50. __next_->~__i_node();
  51. free(__next_);
  52. }
  53. }
  54. __c_node::~__c_node()
  55. {
  56. free(beg_);
  57. if (__next_)
  58. {
  59. __next_->~__c_node();
  60. free(__next_);
  61. }
  62. }
  63. __libcpp_db::__libcpp_db()
  64. : __cbeg_(nullptr),
  65. __cend_(nullptr),
  66. __csz_(0),
  67. __ibeg_(nullptr),
  68. __iend_(nullptr),
  69. __isz_(0)
  70. {
  71. }
  72. __libcpp_db::~__libcpp_db()
  73. {
  74. if (__cbeg_)
  75. {
  76. for (__c_node** p = __cbeg_; p != __cend_; ++p)
  77. {
  78. if (*p != nullptr)
  79. {
  80. (*p)->~__c_node();
  81. free(*p);
  82. }
  83. }
  84. free(__cbeg_);
  85. }
  86. if (__ibeg_)
  87. {
  88. for (__i_node** p = __ibeg_; p != __iend_; ++p)
  89. {
  90. if (*p != nullptr)
  91. {
  92. (*p)->~__i_node();
  93. free(*p);
  94. }
  95. }
  96. free(__ibeg_);
  97. }
  98. }
  99. void*
  100. __libcpp_db::__find_c_from_i(void* __i) const
  101. {
  102. #ifndef _LIBCPP_HAS_NO_THREADS
  103. RLock _(mut());
  104. #endif
  105. __i_node* i = __find_iterator(__i);
  106. _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database.");
  107. return i->__c_ != nullptr ? i->__c_->__c_ : nullptr;
  108. }
  109. void
  110. __libcpp_db::__insert_ic(void* __i, const void* __c)
  111. {
  112. #ifndef _LIBCPP_HAS_NO_THREADS
  113. WLock _(mut());
  114. #endif
  115. if (__cbeg_ == __cend_)
  116. return;
  117. size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
  118. __c_node* c = __cbeg_[hc];
  119. if (c == nullptr)
  120. return;
  121. while (c->__c_ != __c)
  122. {
  123. c = c->__next_;
  124. if (c == nullptr)
  125. return;
  126. }
  127. __i_node* i = __insert_iterator(__i);
  128. c->__add(i);
  129. i->__c_ = c;
  130. }
  131. __c_node*
  132. __libcpp_db::__insert_c(void* __c)
  133. {
  134. #ifndef _LIBCPP_HAS_NO_THREADS
  135. WLock _(mut());
  136. #endif
  137. if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_))
  138. {
  139. size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1);
  140. __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*)));
  141. if (cbeg == nullptr)
  142. #ifndef _LIBCPP_NO_EXCEPTIONS
  143. throw bad_alloc();
  144. #else
  145. abort();
  146. #endif
  147. for (__c_node** p = __cbeg_; p != __cend_; ++p)
  148. {
  149. __c_node* q = *p;
  150. while (q != nullptr)
  151. {
  152. size_t h = hash<void*>()(q->__c_) % nc;
  153. __c_node* r = q->__next_;
  154. q->__next_ = cbeg[h];
  155. cbeg[h] = q;
  156. q = r;
  157. }
  158. }
  159. free(__cbeg_);
  160. __cbeg_ = cbeg;
  161. __cend_ = __cbeg_ + nc;
  162. }
  163. size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
  164. __c_node* p = __cbeg_[hc];
  165. __c_node* r = __cbeg_[hc] =
  166. static_cast<__c_node*>(malloc(sizeof(__c_node)));
  167. if (__cbeg_[hc] == nullptr)
  168. #ifndef _LIBCPP_NO_EXCEPTIONS
  169. throw bad_alloc();
  170. #else
  171. abort();
  172. #endif
  173. r->__c_ = __c;
  174. r->__next_ = p;
  175. ++__csz_;
  176. return r;
  177. }
  178. void
  179. __libcpp_db::__erase_i(void* __i)
  180. {
  181. #ifndef _LIBCPP_HAS_NO_THREADS
  182. WLock _(mut());
  183. #endif
  184. if (__ibeg_ != __iend_)
  185. {
  186. size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
  187. __i_node* p = __ibeg_[hi];
  188. if (p != nullptr)
  189. {
  190. __i_node* q = nullptr;
  191. while (p->__i_ != __i)
  192. {
  193. q = p;
  194. p = p->__next_;
  195. if (p == nullptr)
  196. return;
  197. }
  198. if (q == nullptr)
  199. __ibeg_[hi] = p->__next_;
  200. else
  201. q->__next_ = p->__next_;
  202. __c_node* c = p->__c_;
  203. --__isz_;
  204. if (c != nullptr)
  205. c->__remove(p);
  206. free(p);
  207. }
  208. }
  209. }
  210. void
  211. __libcpp_db::__invalidate_all(void* __c)
  212. {
  213. #ifndef _LIBCPP_HAS_NO_THREADS
  214. WLock _(mut());
  215. #endif
  216. if (__cend_ != __cbeg_)
  217. {
  218. size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
  219. __c_node* p = __cbeg_[hc];
  220. if (p == nullptr)
  221. return;
  222. while (p->__c_ != __c)
  223. {
  224. p = p->__next_;
  225. if (p == nullptr)
  226. return;
  227. }
  228. while (p->end_ != p->beg_)
  229. {
  230. --p->end_;
  231. (*p->end_)->__c_ = nullptr;
  232. }
  233. }
  234. }
  235. __c_node*
  236. __libcpp_db::__find_c_and_lock(void* __c) const
  237. {
  238. #ifndef _LIBCPP_HAS_NO_THREADS
  239. mut().lock();
  240. #endif
  241. if (__cend_ == __cbeg_)
  242. {
  243. #ifndef _LIBCPP_HAS_NO_THREADS
  244. mut().unlock();
  245. #endif
  246. return nullptr;
  247. }
  248. size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
  249. __c_node* p = __cbeg_[hc];
  250. if (p == nullptr)
  251. {
  252. #ifndef _LIBCPP_HAS_NO_THREADS
  253. mut().unlock();
  254. #endif
  255. return nullptr;
  256. }
  257. while (p->__c_ != __c)
  258. {
  259. p = p->__next_;
  260. if (p == nullptr)
  261. {
  262. #ifndef _LIBCPP_HAS_NO_THREADS
  263. mut().unlock();
  264. #endif
  265. return nullptr;
  266. }
  267. }
  268. return p;
  269. }
  270. __c_node*
  271. __libcpp_db::__find_c(void* __c) const
  272. {
  273. size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
  274. __c_node* p = __cbeg_[hc];
  275. _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A");
  276. while (p->__c_ != __c)
  277. {
  278. p = p->__next_;
  279. _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B");
  280. }
  281. return p;
  282. }
  283. void
  284. __libcpp_db::unlock() const
  285. {
  286. #ifndef _LIBCPP_HAS_NO_THREADS
  287. mut().unlock();
  288. #endif
  289. }
  290. void
  291. __libcpp_db::__erase_c(void* __c)
  292. {
  293. #ifndef _LIBCPP_HAS_NO_THREADS
  294. WLock _(mut());
  295. #endif
  296. if (__cend_ != __cbeg_)
  297. {
  298. size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_);
  299. __c_node* p = __cbeg_[hc];
  300. if (p == nullptr)
  301. return;
  302. __c_node* q = nullptr;
  303. _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A");
  304. while (p->__c_ != __c)
  305. {
  306. q = p;
  307. p = p->__next_;
  308. if (p == nullptr)
  309. return;
  310. _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B");
  311. }
  312. if (q == nullptr)
  313. __cbeg_[hc] = p->__next_;
  314. else
  315. q->__next_ = p->__next_;
  316. while (p->end_ != p->beg_)
  317. {
  318. --p->end_;
  319. (*p->end_)->__c_ = nullptr;
  320. }
  321. free(p->beg_);
  322. free(p);
  323. --__csz_;
  324. }
  325. }
  326. void
  327. __libcpp_db::__iterator_copy(void* __i, const void* __i0)
  328. {
  329. #ifndef _LIBCPP_HAS_NO_THREADS
  330. WLock _(mut());
  331. #endif
  332. __i_node* i = __find_iterator(__i);
  333. __i_node* i0 = __find_iterator(__i0);
  334. __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr;
  335. if (i == nullptr && i0 != nullptr)
  336. i = __insert_iterator(__i);
  337. __c_node* c = i != nullptr ? i->__c_ : nullptr;
  338. if (c != c0)
  339. {
  340. if (c != nullptr)
  341. c->__remove(i);
  342. if (i != nullptr)
  343. {
  344. i->__c_ = nullptr;
  345. if (c0 != nullptr)
  346. {
  347. i->__c_ = c0;
  348. i->__c_->__add(i);
  349. }
  350. }
  351. }
  352. }
  353. bool
  354. __libcpp_db::__dereferenceable(const void* __i) const
  355. {
  356. #ifndef _LIBCPP_HAS_NO_THREADS
  357. RLock _(mut());
  358. #endif
  359. __i_node* i = __find_iterator(__i);
  360. return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i);
  361. }
  362. bool
  363. __libcpp_db::__decrementable(const void* __i) const
  364. {
  365. #ifndef _LIBCPP_HAS_NO_THREADS
  366. RLock _(mut());
  367. #endif
  368. __i_node* i = __find_iterator(__i);
  369. return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i);
  370. }
  371. bool
  372. __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const
  373. {
  374. #ifndef _LIBCPP_HAS_NO_THREADS
  375. RLock _(mut());
  376. #endif
  377. __i_node* i = __find_iterator(__i);
  378. return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n);
  379. }
  380. bool
  381. __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const
  382. {
  383. #ifndef _LIBCPP_HAS_NO_THREADS
  384. RLock _(mut());
  385. #endif
  386. __i_node* i = __find_iterator(__i);
  387. return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n);
  388. }
  389. bool
  390. __libcpp_db::__less_than_comparable(const void* __i, const void* __j) const
  391. {
  392. #ifndef _LIBCPP_HAS_NO_THREADS
  393. RLock _(mut());
  394. #endif
  395. __i_node* i = __find_iterator(__i);
  396. __i_node* j = __find_iterator(__j);
  397. __c_node* ci = i != nullptr ? i->__c_ : nullptr;
  398. __c_node* cj = j != nullptr ? j->__c_ : nullptr;
  399. return ci != nullptr && ci == cj;
  400. }
  401. void
  402. __libcpp_db::swap(void* c1, void* c2)
  403. {
  404. #ifndef _LIBCPP_HAS_NO_THREADS
  405. WLock _(mut());
  406. #endif
  407. size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_);
  408. __c_node* p1 = __cbeg_[hc];
  409. _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A");
  410. while (p1->__c_ != c1)
  411. {
  412. p1 = p1->__next_;
  413. _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B");
  414. }
  415. hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_);
  416. __c_node* p2 = __cbeg_[hc];
  417. _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C");
  418. while (p2->__c_ != c2)
  419. {
  420. p2 = p2->__next_;
  421. _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D");
  422. }
  423. std::swap(p1->beg_, p2->beg_);
  424. std::swap(p1->end_, p2->end_);
  425. std::swap(p1->cap_, p2->cap_);
  426. for (__i_node** p = p1->beg_; p != p1->end_; ++p)
  427. (*p)->__c_ = p1;
  428. for (__i_node** p = p2->beg_; p != p2->end_; ++p)
  429. (*p)->__c_ = p2;
  430. }
  431. void
  432. __libcpp_db::__insert_i(void* __i)
  433. {
  434. #ifndef _LIBCPP_HAS_NO_THREADS
  435. WLock _(mut());
  436. #endif
  437. __insert_iterator(__i);
  438. }
  439. void
  440. __c_node::__add(__i_node* i)
  441. {
  442. if (end_ == cap_)
  443. {
  444. size_t nc = 2*static_cast<size_t>(cap_ - beg_);
  445. if (nc == 0)
  446. nc = 1;
  447. __i_node** beg =
  448. static_cast<__i_node**>(malloc(nc * sizeof(__i_node*)));
  449. if (beg == nullptr)
  450. #ifndef _LIBCPP_NO_EXCEPTIONS
  451. throw bad_alloc();
  452. #else
  453. abort();
  454. #endif
  455. if (nc > 1)
  456. memcpy(beg, beg_, nc/2*sizeof(__i_node*));
  457. free(beg_);
  458. beg_ = beg;
  459. end_ = beg_ + nc/2;
  460. cap_ = beg_ + nc;
  461. }
  462. *end_++ = i;
  463. }
  464. // private api
  465. _LIBCPP_HIDDEN
  466. __i_node*
  467. __libcpp_db::__insert_iterator(void* __i)
  468. {
  469. if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_))
  470. {
  471. size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1);
  472. __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*)));
  473. if (ibeg == nullptr)
  474. #ifndef _LIBCPP_NO_EXCEPTIONS
  475. throw bad_alloc();
  476. #else
  477. abort();
  478. #endif
  479. for (__i_node** p = __ibeg_; p != __iend_; ++p)
  480. {
  481. __i_node* q = *p;
  482. while (q != nullptr)
  483. {
  484. size_t h = hash<void*>()(q->__i_) % nc;
  485. __i_node* r = q->__next_;
  486. q->__next_ = ibeg[h];
  487. ibeg[h] = q;
  488. q = r;
  489. }
  490. }
  491. free(__ibeg_);
  492. __ibeg_ = ibeg;
  493. __iend_ = __ibeg_ + nc;
  494. }
  495. size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
  496. __i_node* p = __ibeg_[hi];
  497. __i_node* r = __ibeg_[hi] =
  498. static_cast<__i_node*>(malloc(sizeof(__i_node)));
  499. if (r == nullptr)
  500. #ifndef _LIBCPP_NO_EXCEPTIONS
  501. throw bad_alloc();
  502. #else
  503. abort();
  504. #endif
  505. ::new(r) __i_node(__i, p, nullptr);
  506. ++__isz_;
  507. return r;
  508. }
  509. _LIBCPP_HIDDEN
  510. __i_node*
  511. __libcpp_db::__find_iterator(const void* __i) const
  512. {
  513. __i_node* r = nullptr;
  514. if (__ibeg_ != __iend_)
  515. {
  516. size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_);
  517. for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_)
  518. {
  519. if (nd->__i_ == __i)
  520. {
  521. r = nd;
  522. break;
  523. }
  524. }
  525. }
  526. return r;
  527. }
  528. _LIBCPP_HIDDEN
  529. void
  530. __c_node::__remove(__i_node* p)
  531. {
  532. __i_node** r = find(beg_, end_, p);
  533. _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove");
  534. if (--end_ != r)
  535. memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*));
  536. }
  537. _LIBCPP_END_NAMESPACE_STD
  538. #endif // !defined(_LIBCPP_SGX_CONFIG)