jemalloc cpp new/delete bindings
Adds cpp bindings for jemalloc, along with necessary autoconf settings. This is mostly to add sized deallocation support, which can't be added from C directly. Sized deallocation is ~10% microbench improvement. * Import ax_cxx_compile_stdcxx.m4 from the autoconf repo, seems like the easiest way to get c++14 detection. * Adds various other changes, like CXXFLAGS, to configure.ac. * Adds new rules to Makefile.in for src/jemalloc-cpp.cpp, and a basic unittest. * Both new and delete are overridden, to ensure jemalloc is used for both. * TODO future enhancement of avoiding extra PLT thunks for new and delete - sdallocx and malloc are publicly exported jemalloc symbols, using an alias would link them directly. Unfortunately, was having trouble getting it to play nice with jemalloc's namespace support. Testing: Tested gcc 4.8, gcc 5, gcc 5.2, clang 4.0. Only gcc >= 5 has sized deallocation support, verified that the rest build correctly. Tested mac osx and Centos. Tested --with-jemalloc-prefix and --without-export. This resolves #202.
This commit is contained in:
140
src/jemalloc_cpp.cpp
Normal file
140
src/jemalloc_cpp.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
#include <mutex>
|
||||
#include <new>
|
||||
|
||||
#define JEMALLOC_CPP_CPP_
|
||||
#include "jemalloc/internal/jemalloc_internal.h"
|
||||
|
||||
// All operators in this file are exported.
|
||||
|
||||
// Possibly alias hidden versions of malloc and sdallocx to avoid an extra plt
|
||||
// thunk?
|
||||
//
|
||||
// extern __typeof (sdallocx) sdallocx_int
|
||||
// __attribute ((alias ("sdallocx"),
|
||||
// visibility ("hidden")));
|
||||
//
|
||||
// ... but it needs to work with jemalloc namespaces.
|
||||
|
||||
void *operator new(std::size_t size);
|
||||
void *operator new[](std::size_t size);
|
||||
void *operator new(std::size_t size, const std::nothrow_t&) noexcept;
|
||||
void *operator new[](std::size_t size, const std::nothrow_t&) noexcept;
|
||||
void operator delete(void* ptr) noexcept;
|
||||
void operator delete[](void* ptr) noexcept;
|
||||
void operator delete(void* ptr, const std::nothrow_t&) noexcept;
|
||||
void operator delete[](void* ptr, const std::nothrow_t&) noexcept;
|
||||
|
||||
#if __cpp_sized_deallocation >= 201309
|
||||
/* C++14's sized-delete operators. */
|
||||
void operator delete(void* ptr, std::size_t size) noexcept;
|
||||
void operator delete[](void* ptr, std::size_t size) noexcept;
|
||||
#endif
|
||||
|
||||
|
||||
template <bool IsNoExcept>
|
||||
JEMALLOC_INLINE
|
||||
void *
|
||||
newImpl(std::size_t size) noexcept(IsNoExcept)
|
||||
{
|
||||
void* ptr = je_malloc(size);
|
||||
if (likely(ptr != nullptr))
|
||||
return (ptr);
|
||||
|
||||
while (ptr == nullptr) {
|
||||
std::new_handler handler;
|
||||
// GCC-4.8 and clang 4.0 do not have std::get_new_handler.
|
||||
{
|
||||
static std::mutex mtx;
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
|
||||
handler = std::set_new_handler(nullptr);
|
||||
std::set_new_handler(handler);
|
||||
}
|
||||
if (handler == nullptr)
|
||||
break;
|
||||
|
||||
try {
|
||||
handler();
|
||||
} catch (const std::bad_alloc&) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = je_malloc(size);
|
||||
}
|
||||
|
||||
if (ptr == nullptr && !IsNoExcept)
|
||||
std::__throw_bad_alloc();
|
||||
return (ptr);
|
||||
}
|
||||
|
||||
void *
|
||||
operator new(std::size_t size)
|
||||
{
|
||||
|
||||
return (newImpl<false>(size));
|
||||
}
|
||||
|
||||
void *
|
||||
operator new[](std::size_t size)
|
||||
{
|
||||
|
||||
return (newImpl<false>(size));
|
||||
}
|
||||
|
||||
void *
|
||||
operator new(std::size_t size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
|
||||
return (newImpl<true>(size));
|
||||
}
|
||||
|
||||
void *
|
||||
operator new[](std::size_t size, const std::nothrow_t&) noexcept
|
||||
{
|
||||
|
||||
return (newImpl<true>(size));
|
||||
}
|
||||
|
||||
void
|
||||
operator delete(void* ptr) noexcept
|
||||
{
|
||||
|
||||
je_free(ptr);
|
||||
}
|
||||
|
||||
void
|
||||
operator delete[](void* ptr) noexcept
|
||||
{
|
||||
|
||||
je_free(ptr);
|
||||
}
|
||||
|
||||
void
|
||||
operator delete(void* ptr, const std::nothrow_t&) noexcept
|
||||
{
|
||||
|
||||
je_free(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void* ptr, const std::nothrow_t&) noexcept
|
||||
{
|
||||
|
||||
je_free(ptr);
|
||||
}
|
||||
|
||||
#if __cpp_sized_deallocation >= 201309
|
||||
|
||||
void
|
||||
operator delete(void* ptr, std::size_t size) noexcept
|
||||
{
|
||||
|
||||
je_sdallocx(ptr, size, /*flags=*/0);
|
||||
}
|
||||
|
||||
void operator delete[](void* ptr, std::size_t size) noexcept
|
||||
{
|
||||
|
||||
je_sdallocx(ptr, size, /*flags=*/0);
|
||||
}
|
||||
|
||||
#endif // __cpp_sized_deallocation
|
Reference in New Issue
Block a user