debug.cpp 13 KB

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