diff options
author | Dave Watson <davejwatson@fb.com> | 2016-10-23 22:56:30 (GMT) |
---|---|---|
committer | Jason Evans <jasone@canonware.com> | 2016-12-13 02:36:06 (GMT) |
commit | 2319152d9f5d9b33eebc36a50ccf4239f31c1ad9 (patch) | |
tree | 44a848c13219a110dec96d2969f6135f2a3c54f7 /src/jemalloc_cpp.cpp | |
parent | d4c5aceb7cb5c5cf7a6dfd62e072c7dd12188998 (diff) | |
download | jemalloc-2319152d9f5d9b33eebc36a50ccf4239f31c1ad9.zip jemalloc-2319152d9f5d9b33eebc36a50ccf4239f31c1ad9.tar.gz jemalloc-2319152d9f5d9b33eebc36a50ccf4239f31c1ad9.tar.bz2 |
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.
Diffstat (limited to 'src/jemalloc_cpp.cpp')
-rw-r--r-- | src/jemalloc_cpp.cpp | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/jemalloc_cpp.cpp b/src/jemalloc_cpp.cpp new file mode 100644 index 0000000..4c5756b --- /dev/null +++ b/src/jemalloc_cpp.cpp @@ -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 |