summaryrefslogtreecommitdiffstats
path: root/src/jemalloc_cpp.cpp
diff options
context:
space:
mode:
authorDave Watson <davejwatson@fb.com>2016-10-23 22:56:30 (GMT)
committerJason Evans <jasone@canonware.com>2016-12-13 02:36:06 (GMT)
commit2319152d9f5d9b33eebc36a50ccf4239f31c1ad9 (patch)
tree44a848c13219a110dec96d2969f6135f2a3c54f7 /src/jemalloc_cpp.cpp
parentd4c5aceb7cb5c5cf7a6dfd62e072c7dd12188998 (diff)
downloadjemalloc-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.cpp140
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