Track malloc size with a header for SHOW_MEMORY

This commit is contained in:
2024-03-14 15:30:46 -07:00
parent ee36bda8f8
commit b817e3c749
4 changed files with 29 additions and 26 deletions

View File

@@ -41,45 +41,47 @@ operator<=>(const std::span<const uint8_t> &lhs,
// GCOVR_EXCL_START
#if SHOW_MEMORY
#ifdef __APPLE__
#include <malloc/malloc.h>
#else
#include <malloc.h>
#endif
inline int64_t mallocBytes = 0;
inline int64_t peakMallocBytes = 0;
constexpr auto kIntMallocHeaderSize = 16;
#endif
// malloc that aborts on OOM and thus always returns a non-null pointer
// malloc that aborts on OOM and thus always returns a non-null pointer. Must be
// paired with `safe_free`.
__attribute__((always_inline)) inline void *safe_malloc(size_t s) {
#if SHOW_MEMORY
mallocBytes += s;
if (mallocBytes > peakMallocBytes) {
peakMallocBytes = mallocBytes;
}
void *p = malloc(s + kIntMallocHeaderSize);
if (p == nullptr) {
abort();
}
memcpy(p, &s, sizeof(s));
return (char *)p + kIntMallocHeaderSize;
#else
void *p = malloc(s);
if (p == nullptr) {
abort();
}
#if SHOW_MEMORY
#ifdef __APPLE__
mallocBytes += s;
#else
mallocBytes += malloc_usable_size(p);
#endif
if (mallocBytes > peakMallocBytes) {
peakMallocBytes = mallocBytes;
}
#endif
return p;
#endif
}
// Must be paired with `safe_malloc`.
//
// There's nothing safer about this than free. Only called safe_free for
// symmetry with safe_malloc.
__attribute__((always_inline)) inline void safe_free(void *p) {
#if SHOW_MEMORY
#ifdef __APPLE__
mallocBytes -= malloc_size(p);
size_t s;
memcpy(&s, (char *)p - kIntMallocHeaderSize, sizeof(s));
mallocBytes -= s;
free((char *)p - kIntMallocHeaderSize);
#else
mallocBytes -= malloc_usable_size(p);
#endif
#endif
free(p);
#endif
}
// ==================== BEGIN ARENA IMPL ====================
@@ -164,7 +166,7 @@ inline Arena::Arena(int initialSize) : impl(nullptr) {
inline void onDestroy(Arena::ArenaImpl *impl) {
while (impl) {
auto *prev = impl->prev;
free(impl);
safe_free(impl);
impl = prev;
}
}