diff options
author | Nathan Sidwell <nathan@acm.org> | 2022-02-07 22:33:08 +0300 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2022-02-14 14:59:31 +0300 |
commit | 995c4f306890ad379de19106f053238ce89f1483 (patch) | |
tree | 95fc23f27a9292f037feaa3c71544ae122b48b4d /libcxxabi/src/demangle | |
parent | 5a43a278f7f6a9bba0a630634534a37e060f24d0 (diff) |
[demangler] Fix buffer growth
The output buffer growth algorithm had a few issues:
a) An off-by-one error in the initial size check, which uses
'>='. This error was safe, but could cause us to reallocate when there
was no need.
b) An inconsistency between the initial size check (>=) and the
post-doubling check (>). The latter was somewhat obscured by the
swapped operands.
c) There would be many reallocs with an initially-small buffer. Add a
little initialization hysteresis.
Reviewed By: ChuanqiXu
Differential Revision: https://reviews.llvm.org/D119177
Diffstat (limited to 'libcxxabi/src/demangle')
-rw-r--r-- | libcxxabi/src/demangle/Utility.h | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/libcxxabi/src/demangle/Utility.h b/libcxxabi/src/demangle/Utility.h index 93ef2aae34ba..97272ae64fb7 100644 --- a/libcxxabi/src/demangle/Utility.h +++ b/libcxxabi/src/demangle/Utility.h @@ -33,12 +33,14 @@ class OutputBuffer { size_t CurrentPosition = 0; size_t BufferCapacity = 0; - // Ensure there is at least n more positions in buffer. + // Ensure there are at least N more positions in the buffer. void grow(size_t N) { - if (N + CurrentPosition >= BufferCapacity) { - BufferCapacity *= 2; - if (BufferCapacity < N + CurrentPosition) - BufferCapacity = N + CurrentPosition; + size_t Need = N + CurrentPosition; + if (Need > BufferCapacity) { + // Avoid many reallocations during startup, with a bit of hysteresis. + constexpr size_t MinInitAlloc = 1024; + Need = std::max(Need, MinInitAlloc); + BufferCapacity = std::max(Need, BufferCapacity * 2); Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity)); if (Buffer == nullptr) std::terminate(); |