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