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