debug.cpp 14 KB

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