modernize and fix SpanSet iterator handling

In addition to just being more readable, we fix github issue #1573
"Unable to build gperftools with _GLIBCXX_DEBUG flag".
This commit is contained in:
Aliaksei Kandratsenka 2024-11-23 13:36:47 -05:00
parent e9fbbf9450
commit c4120da88e
2 changed files with 19 additions and 21 deletions

View File

@ -279,7 +279,7 @@ Span* PageHeap::AllocLarge(Length n) {
bound.length = n;
// First search the NORMAL spans..
SpanSet::iterator place = large_normal_.upper_bound(SpanPtrWithLength(&bound));
SpanSetIter place = large_normal_.upper_bound(SpanPtrWithLength(&bound));
if (place != large_normal_.end()) {
best = place->span;
best_normal = best;
@ -512,7 +512,7 @@ void PageHeap::PrependToFreeList(Span* span) {
SpanSet *set = &large_normal_;
if (span->location == Span::ON_RETURNED_FREELIST)
set = &large_returned_;
std::pair<SpanSet::iterator, bool> p =
std::pair<SpanSetIter, bool> p =
set->insert(SpanPtrWithLength(span));
ASSERT(p.second); // We never have duplicates since span->start is unique.
span->SetSpanSetIterator(p.first);
@ -539,7 +539,7 @@ void PageHeap::RemoveFromFreeList(Span* span) {
SpanSet *set = &large_normal_;
if (span->location == Span::ON_RETURNED_FREELIST)
set = &large_returned_;
SpanSet::iterator iter = span->ExtractSpanSetIterator();
SpanSetIter iter = span->ExtractSpanSetIterator();
ASSERT(iter->span == span);
ASSERT(set->find(SpanPtrWithLength(span)) == iter);
set->erase(iter);
@ -682,11 +682,11 @@ void PageHeap::GetLargeSpanStatsLocked(LargeSpanStats* result) {
result->spans = 0;
result->normal_pages = 0;
result->returned_pages = 0;
for (SpanSet::iterator it = large_normal_.begin(); it != large_normal_.end(); ++it) {
for (SpanSetIter it = large_normal_.begin(); it != large_normal_.end(); ++it) {
result->normal_pages += it->length;
result->spans++;
}
for (SpanSet::iterator it = large_returned_.begin(); it != large_returned_.end(); ++it) {
for (SpanSetIter it = large_returned_.begin(); it != large_returned_.end(); ++it) {
result->returned_pages += it->length;
result->spans++;
}
@ -817,7 +817,7 @@ bool PageHeap::CheckList(Span* list, Length min_pages, Length max_pages,
}
bool PageHeap::CheckSet(SpanSet* spanset, Length min_pages,int freelist) {
for (SpanSet::iterator it = spanset->begin(); it != spanset->end(); ++it) {
for (SpanSetIter it = spanset->begin(); it != spanset->end(); ++it) {
Span* s = it->span;
CHECK_CONDITION(s->length == it->length);
CHECK_CONDITION(s->location == freelist); // NORMAL or RETURNED

View File

@ -44,7 +44,6 @@
namespace tcmalloc {
struct SpanBestFitLess;
struct Span;
// Store a pointer to a span along with a cached copy of its length.
@ -58,13 +57,14 @@ struct SpanPtrWithLength {
Span* span;
Length length;
};
typedef std::set<SpanPtrWithLength, SpanBestFitLess, STLPageHeapAllocator<SpanPtrWithLength, void> > SpanSet;
// Comparator for best-fit search, with address order as a tie-breaker.
struct SpanBestFitLess {
bool operator()(SpanPtrWithLength a, SpanPtrWithLength b) const;
};
using SpanSet = std::set<SpanPtrWithLength, SpanBestFitLess, STLPageHeapAllocator<SpanPtrWithLength, void>>;
using SpanSetIter = SpanSet::iterator;
// Information kept for a span (a contiguous run of pages).
struct Span {
PageID start; // Starting page number
@ -78,7 +78,7 @@ struct Span {
// this span into set of large spans. It is used to quickly delete
// spans from those sets. span_iter_space is space for such
// iterator which lifetime is controlled explicitly.
char span_iter_space[sizeof(SpanSet::iterator)];
alignas(SpanSetIter) char span_iter_space[sizeof(SpanSetIter)];
};
unsigned int refcount : 16; // Number of non-free objects
unsigned int sizeclass : 8; // Size-class for small objects (or 0)
@ -92,9 +92,9 @@ struct Span {
// Sets iterator stored in span_iter_space.
// Requires has_span_iter == 0.
void SetSpanSetIterator(const SpanSet::iterator& iter);
void SetSpanSetIterator(const SpanSetIter& iter);
// Copies out and destroys iterator stored in span_iter_space.
SpanSet::iterator ExtractSpanSetIterator();
SpanSetIter ExtractSpanSetIterator();
// What freelist the span is on: IN_USE if on none, or normal or returned
enum { IN_USE, ON_NORMAL_FREELIST, ON_RETURNED_FREELIST };
@ -113,23 +113,21 @@ inline bool SpanBestFitLess::operator()(SpanPtrWithLength a, SpanPtrWithLength b
return a.span->start < b.span->start;
}
inline void Span::SetSpanSetIterator(const SpanSet::iterator& iter) {
inline void Span::SetSpanSetIterator(const SpanSetIter& iter) {
ASSERT(!has_span_iter);
has_span_iter = 1;
new (span_iter_space) SpanSet::iterator(iter);
new (span_iter_space) SpanSetIter(iter);
}
inline SpanSet::iterator Span::ExtractSpanSetIterator() {
typedef SpanSet::iterator iterator_type;
inline SpanSetIter Span::ExtractSpanSetIterator() {
ASSERT(has_span_iter);
has_span_iter = 0;
iterator_type* this_iter =
reinterpret_cast<iterator_type*>(span_iter_space);
iterator_type retval = *this_iter;
this_iter->~iterator_type();
SpanSetIter* this_iter =
reinterpret_cast<SpanSetIter*>(span_iter_space);
SpanSetIter retval = *this_iter;
this_iter->~SpanSetIter();
return retval;
}