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 #define _LIBCPP_DEBUG2 1 11 #include "__config" 12 #include "__debug" 13 #include "functional" 14 #include "algorithm" 15 #include "__hash_table" 16 #include "mutex" 17 18 _LIBCPP_BEGIN_NAMESPACE_STD 19 20 _LIBCPP_FUNC_VIS 21 __libcpp_db* 22 __get_db() 23 { 24 static __libcpp_db db; 25 return &db; 26 } 27 28 _LIBCPP_FUNC_VIS 29 const __libcpp_db* 30 __get_const_db() 31 { 32 return __get_db(); 33 } 34 35 namespace 36 { 37 38 typedef mutex mutex_type; 39 typedef lock_guard<mutex_type> WLock; 40 typedef lock_guard<mutex_type> RLock; 41 42 mutex_type& 43 mut() 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 108 void* 109 __libcpp_db::__find_c_from_i(void* __i) const 110 { 111 RLock _(mut()); 112 __i_node* i = __find_iterator(__i); 113 _LIBCPP_ASSERT(i != nullptr, "iterator not found in debug database."); 114 return i->__c_ != nullptr ? i->__c_->__c_ : nullptr; 115 } 116 117 void 118 __libcpp_db::__insert_ic(void* __i, const void* __c) 119 { 120 WLock _(mut()); 121 __i_node* i = __insert_iterator(__i); 122 const char* errmsg = 123 "Container constructed in a translation unit with debug mode disabled." 124 " But it is being used in a translation unit with debug mode enabled." 125 " Enable it in the other translation unit with #define _LIBCPP_DEBUG2 1"; 126 _LIBCPP_ASSERT(__cbeg_ != __cend_, errmsg); 127 size_t hc = hash<const void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 128 __c_node* c = __cbeg_[hc]; 129 _LIBCPP_ASSERT(c != nullptr, errmsg); 130 while (c->__c_ != __c) 131 { 132 c = c->__next_; 133 _LIBCPP_ASSERT(c != nullptr, errmsg); 134 } 135 c->__add(i); 136 i->__c_ = c; 137 } 138 139 __c_node* 140 __libcpp_db::__insert_c(void* __c) 141 { 142 WLock _(mut()); 143 if (__csz_ + 1 > static_cast<size_t>(__cend_ - __cbeg_)) 144 { 145 size_t nc = __next_prime(2*static_cast<size_t>(__cend_ - __cbeg_) + 1); 146 __c_node** cbeg = static_cast<__c_node**>(calloc(nc, sizeof(void*))); 147 if (cbeg == nullptr) 148 #ifndef _LIBCPP_NO_EXCEPTIONS 149 throw bad_alloc(); 150 #else 151 abort(); 152 #endif 153 for (__c_node** p = __cbeg_; p != __cend_; ++p) 154 { 155 __c_node* q = *p; 156 while (q != nullptr) 157 { 158 size_t h = hash<void*>()(q->__c_) % nc; 159 __c_node* r = q->__next_; 160 q->__next_ = cbeg[h]; 161 cbeg[h] = q; 162 q = r; 163 } 164 } 165 free(__cbeg_); 166 __cbeg_ = cbeg; 167 __cend_ = __cbeg_ + nc; 168 } 169 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 170 __c_node* p = __cbeg_[hc]; 171 __c_node* r = __cbeg_[hc] = 172 static_cast<__c_node*>(malloc(sizeof(__c_node))); 173 if (__cbeg_[hc] == nullptr) 174 #ifndef _LIBCPP_NO_EXCEPTIONS 175 throw bad_alloc(); 176 #else 177 abort(); 178 #endif 179 r->__c_ = __c; 180 r->__next_ = p; 181 ++__csz_; 182 return r; 183 } 184 185 void 186 __libcpp_db::__erase_i(void* __i) 187 { 188 WLock _(mut()); 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 free(p); 209 --__isz_; 210 if (c != nullptr) 211 c->__remove(p); 212 } 213 } 214 } 215 216 void 217 __libcpp_db::__invalidate_all(void* __c) 218 { 219 WLock _(mut()); 220 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 221 __c_node* p = __cbeg_[hc]; 222 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __invalidate_all A"); 223 while (p->__c_ != __c) 224 { 225 p = p->__next_; 226 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __invalidate_all B"); 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 mut().lock(); 239 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 240 __c_node* p = __cbeg_[hc]; 241 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c_and_lock A"); 242 while (p->__c_ != __c) 243 { 244 p = p->__next_; 245 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c_and_lock B"); 246 } 247 return p; 248 } 249 250 __c_node* 251 __libcpp_db::__find_c(void* __c) const 252 { 253 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 254 __c_node* p = __cbeg_[hc]; 255 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c A"); 256 while (p->__c_ != __c) 257 { 258 p = p->__next_; 259 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __find_c B"); 260 } 261 return p; 262 } 263 264 void 265 __libcpp_db::unlock() const 266 { 267 mut().unlock(); 268 } 269 270 void 271 __libcpp_db::__erase_c(void* __c) 272 { 273 WLock _(mut()); 274 size_t hc = hash<void*>()(__c) % static_cast<size_t>(__cend_ - __cbeg_); 275 __c_node* p = __cbeg_[hc]; 276 __c_node* q = nullptr; 277 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c A"); 278 while (p->__c_ != __c) 279 { 280 q = p; 281 p = p->__next_; 282 _LIBCPP_ASSERT(p != nullptr, "debug mode internal logic error __erase_c B"); 283 } 284 if (q == nullptr) 285 __cbeg_[hc] = p->__next_; 286 else 287 q->__next_ = p->__next_; 288 while (p->end_ != p->beg_) 289 { 290 --p->end_; 291 (*p->end_)->__c_ = nullptr; 292 } 293 free(p->beg_); 294 free(p); 295 --__csz_; 296 } 297 298 void 299 __libcpp_db::__iterator_copy(void* __i, const void* __i0) 300 { 301 WLock _(mut()); 302 __i_node* i = __find_iterator(__i); 303 __i_node* i0 = __find_iterator(__i0); 304 __c_node* c0 = i0 != nullptr ? i0->__c_ : nullptr; 305 if (i == nullptr && i0 != nullptr) 306 i = __insert_iterator(__i); 307 __c_node* c = i != nullptr ? i->__c_ : nullptr; 308 if (c != c0) 309 { 310 if (c != nullptr) 311 c->__remove(i); 312 if (i != nullptr) 313 { 314 i->__c_ = nullptr; 315 if (c0 != nullptr) 316 { 317 i->__c_ = c0; 318 i->__c_->__add(i); 319 } 320 } 321 } 322 } 323 324 bool 325 __libcpp_db::__dereferenceable(const void* __i) const 326 { 327 RLock _(mut()); 328 __i_node* i = __find_iterator(__i); 329 return i != nullptr && i->__c_ != nullptr && i->__c_->__dereferenceable(__i); 330 } 331 332 bool 333 __libcpp_db::__decrementable(const void* __i) const 334 { 335 RLock _(mut()); 336 __i_node* i = __find_iterator(__i); 337 return i != nullptr && i->__c_ != nullptr && i->__c_->__decrementable(__i); 338 } 339 340 bool 341 __libcpp_db::__addable(const void* __i, ptrdiff_t __n) const 342 { 343 RLock _(mut()); 344 __i_node* i = __find_iterator(__i); 345 return i != nullptr && i->__c_ != nullptr && i->__c_->__addable(__i, __n); 346 } 347 348 bool 349 __libcpp_db::__subscriptable(const void* __i, ptrdiff_t __n) const 350 { 351 RLock _(mut()); 352 __i_node* i = __find_iterator(__i); 353 return i != nullptr && i->__c_ != nullptr && i->__c_->__subscriptable(__i, __n); 354 } 355 356 bool 357 __libcpp_db::__comparable(const void* __i, const void* __j) const 358 { 359 RLock _(mut()); 360 __i_node* i = __find_iterator(__i); 361 __i_node* j = __find_iterator(__j); 362 __c_node* ci = i != nullptr ? i->__c_ : nullptr; 363 __c_node* cj = j != nullptr ? j->__c_ : nullptr; 364 return ci != nullptr && ci == cj; 365 } 366 367 void 368 __libcpp_db::swap(void* c1, void* c2) 369 { 370 WLock _(mut()); 371 size_t hc = hash<void*>()(c1) % static_cast<size_t>(__cend_ - __cbeg_); 372 __c_node* p1 = __cbeg_[hc]; 373 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap A"); 374 while (p1->__c_ != c1) 375 { 376 p1 = p1->__next_; 377 _LIBCPP_ASSERT(p1 != nullptr, "debug mode internal logic error swap B"); 378 } 379 hc = hash<void*>()(c2) % static_cast<size_t>(__cend_ - __cbeg_); 380 __c_node* p2 = __cbeg_[hc]; 381 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap C"); 382 while (p2->__c_ != c2) 383 { 384 p2 = p2->__next_; 385 _LIBCPP_ASSERT(p2 != nullptr, "debug mode internal logic error swap D"); 386 } 387 std::swap(p1->beg_, p2->beg_); 388 std::swap(p1->end_, p2->end_); 389 std::swap(p1->cap_, p2->cap_); 390 for (__i_node** p = p1->beg_; p != p1->end_; ++p) 391 (*p)->__c_ = p1; 392 for (__i_node** p = p2->beg_; p != p2->end_; ++p) 393 (*p)->__c_ = p2; 394 } 395 396 void 397 __libcpp_db::__insert_i(void* __i) 398 { 399 WLock _(mut()); 400 __insert_iterator(__i); 401 } 402 403 void 404 __c_node::__add(__i_node* i) 405 { 406 if (end_ == cap_) 407 { 408 size_t nc = 2*static_cast<size_t>(cap_ - beg_); 409 if (nc == 0) 410 nc = 1; 411 __i_node** beg = 412 static_cast<__i_node**>(malloc(nc * sizeof(__i_node*))); 413 if (beg == nullptr) 414 #ifndef _LIBCPP_NO_EXCEPTIONS 415 throw bad_alloc(); 416 #else 417 abort(); 418 #endif 419 if (nc > 1) 420 memcpy(beg, beg_, nc/2*sizeof(__i_node*)); 421 free(beg_); 422 beg_ = beg; 423 end_ = beg_ + nc/2; 424 cap_ = beg_ + nc; 425 } 426 *end_++ = i; 427 } 428 429 // private api 430 431 _LIBCPP_HIDDEN 432 __i_node* 433 __libcpp_db::__insert_iterator(void* __i) 434 { 435 if (__isz_ + 1 > static_cast<size_t>(__iend_ - __ibeg_)) 436 { 437 size_t nc = __next_prime(2*static_cast<size_t>(__iend_ - __ibeg_) + 1); 438 __i_node** ibeg = static_cast<__i_node**>(calloc(nc, sizeof(void*))); 439 if (ibeg == nullptr) 440 #ifndef _LIBCPP_NO_EXCEPTIONS 441 throw bad_alloc(); 442 #else 443 abort(); 444 #endif 445 for (__i_node** p = __ibeg_; p != __iend_; ++p) 446 { 447 __i_node* q = *p; 448 while (q != nullptr) 449 { 450 size_t h = hash<void*>()(q->__i_) % nc; 451 __i_node* r = q->__next_; 452 q->__next_ = ibeg[h]; 453 ibeg[h] = q; 454 q = r; 455 } 456 } 457 free(__ibeg_); 458 __ibeg_ = ibeg; 459 __iend_ = __ibeg_ + nc; 460 } 461 size_t hi = hash<void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); 462 __i_node* p = __ibeg_[hi]; 463 __i_node* r = __ibeg_[hi] = 464 static_cast<__i_node*>(malloc(sizeof(__i_node))); 465 if (r == nullptr) 466 #ifndef _LIBCPP_NO_EXCEPTIONS 467 throw bad_alloc(); 468 #else 469 abort(); 470 #endif 471 ::new(r) __i_node(__i, p, nullptr); 472 ++__isz_; 473 return r; 474 } 475 476 _LIBCPP_HIDDEN 477 __i_node* 478 __libcpp_db::__find_iterator(const void* __i) const 479 { 480 __i_node* r = nullptr; 481 if (__ibeg_ != __iend_) 482 { 483 size_t h = hash<const void*>()(__i) % static_cast<size_t>(__iend_ - __ibeg_); 484 for (__i_node* nd = __ibeg_[h]; nd != nullptr; nd = nd->__next_) 485 { 486 if (nd->__i_ == __i) 487 { 488 r = nd; 489 break; 490 } 491 } 492 } 493 return r; 494 } 495 496 _LIBCPP_HIDDEN 497 void 498 __c_node::__remove(__i_node* p) 499 { 500 __i_node** r = find(beg_, end_, p); 501 _LIBCPP_ASSERT(r != end_, "debug mode internal logic error __c_node::__remove"); 502 if (--end_ != r) 503 memmove(r, r+1, static_cast<size_t>(end_ - r)*sizeof(__i_node*)); 504 } 505 506 _LIBCPP_END_NAMESPACE_STD 507