Skip to content

Commit 88c4823

Browse files
Abseil Teamcopybara-github
authored andcommitted
Search more aggressively for open slots in absl::internal_stacktrace::BorrowedFixupBuffer
This lets us avoid heap allocations in more situations than before. PiperOrigin-RevId: 841851984 Change-Id: Ibd16b0b87c250c504c8d1119d9b9eb4031067c28
1 parent f17f907 commit 88c4823

File tree

2 files changed

+29
-32
lines changed

2 files changed

+29
-32
lines changed

absl/debugging/internal/borrowed_fixup_buffer.cc

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <atomic>
2323
#include <iterator>
24+
#include <utility>
2425

2526
#include "absl/base/attributes.h"
2627
#include "absl/base/config.h"
@@ -46,28 +47,27 @@ ABSL_CONST_INIT BorrowedFixupBuffer::FixupStackBuffer
4647

4748
BorrowedFixupBuffer::~BorrowedFixupBuffer() {
4849
if (borrowed_) {
49-
Unlock();
50+
std::move(*this).Unlock();
5051
} else {
5152
base_internal::LowLevelAlloc::Free(frames_);
5253
}
5354
}
5455

55-
BorrowedFixupBuffer::BorrowedFixupBuffer(size_t length) {
56-
FixupStackBuffer* fixup_buffer =
57-
0 < length && length <= FixupStackBuffer::kMaxStackElements ? TryLock()
58-
: nullptr;
59-
borrowed_ = fixup_buffer != nullptr;
56+
BorrowedFixupBuffer::BorrowedFixupBuffer(size_t length)
57+
: borrowed_(0 < length && length <= FixupStackBuffer::kMaxStackElements
58+
? TryLock()
59+
: nullptr) {
6060
if (borrowed_) {
61-
InitViaBorrow(fixup_buffer);
61+
InitViaBorrow();
6262
} else {
6363
InitViaAllocation(length);
6464
}
6565
}
6666

67-
void BorrowedFixupBuffer::InitViaBorrow(FixupStackBuffer* borrowed_buffer) {
67+
void BorrowedFixupBuffer::InitViaBorrow() {
6868
assert(borrowed_);
69-
frames_ = borrowed_buffer->frames;
70-
sizes_ = borrowed_buffer->sizes;
69+
frames_ = borrowed_->frames;
70+
sizes_ = borrowed_->sizes;
7171
}
7272

7373
void BorrowedFixupBuffer::InitViaAllocation(size_t length) {
@@ -92,25 +92,25 @@ void BorrowedFixupBuffer::InitViaAllocation(size_t length) {
9292
length * sizeof(*frames_))) int[length];
9393
}
9494

95-
BorrowedFixupBuffer::FixupStackBuffer* BorrowedFixupBuffer::Find() {
96-
size_t i = absl::Hash<const void*>()(this) %
97-
std::size(FixupStackBuffer::g_instances);
98-
return &FixupStackBuffer::g_instances[i];
99-
}
100-
10195
[[nodiscard]] BorrowedFixupBuffer::FixupStackBuffer*
10296
BorrowedFixupBuffer::TryLock() {
103-
FixupStackBuffer* instance = Find();
104-
// Use memory_order_acquire to ensure that no reads and writes on the borrowed
105-
// buffer are reordered before the borrowing.
106-
return !instance->in_use.test_and_set(std::memory_order_acquire) ? instance
107-
: nullptr;
97+
constexpr size_t kNumSlots = std::size(FixupStackBuffer::g_instances);
98+
const size_t i = absl::Hash<const void*>()(this) % kNumSlots;
99+
for (size_t k = 0; k < kNumSlots; ++k) {
100+
auto* instance = &FixupStackBuffer::g_instances[(i + k) % kNumSlots];
101+
// Use memory_order_acquire to ensure that no reads and writes on the
102+
// borrowed buffer are reordered before the borrowing.
103+
if (!instance->in_use.test_and_set(std::memory_order_acquire)) {
104+
return instance;
105+
}
106+
}
107+
return nullptr;
108108
}
109109

110-
void BorrowedFixupBuffer::Unlock() {
110+
void BorrowedFixupBuffer::Unlock() && {
111111
// Use memory_order_release to ensure that no reads and writes on the borrowed
112112
// buffer are reordered after the borrowing.
113-
Find()->in_use.clear(std::memory_order_release);
113+
borrowed_->in_use.clear(std::memory_order_release);
114114
}
115115

116116
} // namespace internal_stacktrace

absl/debugging/internal/borrowed_fixup_buffer.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,26 +42,23 @@ class BorrowedFixupBuffer {
4242
int* sizes() const { return sizes_; }
4343

4444
private:
45+
struct FixupStackBuffer;
46+
4547
uintptr_t* frames_;
4648
int* sizes_;
4749

48-
// Have we borrowed a pre-existing buffer (vs. allocated our own)?
49-
bool borrowed_;
50+
// The borrowed pre-existing buffer, if any (if we haven't allocated our own)
51+
FixupStackBuffer* const borrowed_;
5052

51-
struct FixupStackBuffer;
52-
53-
void InitViaBorrow(FixupStackBuffer* borrowed_buffer);
53+
void InitViaBorrow();
5454
void InitViaAllocation(size_t length);
5555

56-
// Returns a non-null pointer to a buffer that could be potentially borrowed.
57-
FixupStackBuffer* Find();
58-
5956
// Attempts to opportunistically borrow a small buffer in a thread- and
6057
// signal-safe manner. Returns nullptr on failure.
6158
[[nodiscard]] FixupStackBuffer* TryLock();
6259

6360
// Returns the borrowed buffer.
64-
void Unlock();
61+
void Unlock() &&;
6562

6663
BorrowedFixupBuffer(const BorrowedFixupBuffer&) = delete;
6764
BorrowedFixupBuffer& operator=(const BorrowedFixupBuffer&) = delete;

0 commit comments

Comments
 (0)