1*8e33eff8Schristos #include <mutex> 2*8e33eff8Schristos #include <new> 3*8e33eff8Schristos 4*8e33eff8Schristos #define JEMALLOC_CPP_CPP_ 5*8e33eff8Schristos #ifdef __cplusplus 6*8e33eff8Schristos extern "C" { 7*8e33eff8Schristos #endif 8*8e33eff8Schristos 9*8e33eff8Schristos #include "jemalloc/internal/jemalloc_preamble.h" 10*8e33eff8Schristos #include "jemalloc/internal/jemalloc_internal_includes.h" 11*8e33eff8Schristos 12*8e33eff8Schristos #ifdef __cplusplus 13*8e33eff8Schristos } 14*8e33eff8Schristos #endif 15*8e33eff8Schristos 16*8e33eff8Schristos // All operators in this file are exported. 17*8e33eff8Schristos 18*8e33eff8Schristos // Possibly alias hidden versions of malloc and sdallocx to avoid an extra plt 19*8e33eff8Schristos // thunk? 20*8e33eff8Schristos // 21*8e33eff8Schristos // extern __typeof (sdallocx) sdallocx_int 22*8e33eff8Schristos // __attribute ((alias ("sdallocx"), 23*8e33eff8Schristos // visibility ("hidden"))); 24*8e33eff8Schristos // 25*8e33eff8Schristos // ... but it needs to work with jemalloc namespaces. 26*8e33eff8Schristos 27*8e33eff8Schristos void *operator new(std::size_t size); 28*8e33eff8Schristos void *operator new[](std::size_t size); 29*8e33eff8Schristos void *operator new(std::size_t size, const std::nothrow_t &) noexcept; 30*8e33eff8Schristos void *operator new[](std::size_t size, const std::nothrow_t &) noexcept; 31*8e33eff8Schristos void operator delete(void *ptr) noexcept; 32*8e33eff8Schristos void operator delete[](void *ptr) noexcept; 33*8e33eff8Schristos void operator delete(void *ptr, const std::nothrow_t &) noexcept; 34*8e33eff8Schristos void operator delete[](void *ptr, const std::nothrow_t &) noexcept; 35*8e33eff8Schristos 36*8e33eff8Schristos #if __cpp_sized_deallocation >= 201309 37*8e33eff8Schristos /* C++14's sized-delete operators. */ 38*8e33eff8Schristos void operator delete(void *ptr, std::size_t size) noexcept; 39*8e33eff8Schristos void operator delete[](void *ptr, std::size_t size) noexcept; 40*8e33eff8Schristos #endif 41*8e33eff8Schristos 42*8e33eff8Schristos JEMALLOC_NOINLINE 43*8e33eff8Schristos static void * 44*8e33eff8Schristos handleOOM(std::size_t size, bool nothrow) { 45*8e33eff8Schristos void *ptr = nullptr; 46*8e33eff8Schristos 47*8e33eff8Schristos while (ptr == nullptr) { 48*8e33eff8Schristos std::new_handler handler; 49*8e33eff8Schristos // GCC-4.8 and clang 4.0 do not have std::get_new_handler. 50*8e33eff8Schristos { 51*8e33eff8Schristos static std::mutex mtx; 52*8e33eff8Schristos std::lock_guard<std::mutex> lock(mtx); 53*8e33eff8Schristos 54*8e33eff8Schristos handler = std::set_new_handler(nullptr); 55*8e33eff8Schristos std::set_new_handler(handler); 56*8e33eff8Schristos } 57*8e33eff8Schristos if (handler == nullptr) 58*8e33eff8Schristos break; 59*8e33eff8Schristos 60*8e33eff8Schristos try { 61*8e33eff8Schristos handler(); 62*8e33eff8Schristos } catch (const std::bad_alloc &) { 63*8e33eff8Schristos break; 64*8e33eff8Schristos } 65*8e33eff8Schristos 66*8e33eff8Schristos ptr = je_malloc(size); 67*8e33eff8Schristos } 68*8e33eff8Schristos 69*8e33eff8Schristos if (ptr == nullptr && !nothrow) 70*8e33eff8Schristos std::__throw_bad_alloc(); 71*8e33eff8Schristos return ptr; 72*8e33eff8Schristos } 73*8e33eff8Schristos 74*8e33eff8Schristos template <bool IsNoExcept> 75*8e33eff8Schristos JEMALLOC_ALWAYS_INLINE 76*8e33eff8Schristos void * 77*8e33eff8Schristos newImpl(std::size_t size) noexcept(IsNoExcept) { 78*8e33eff8Schristos void *ptr = je_malloc(size); 79*8e33eff8Schristos if (likely(ptr != nullptr)) 80*8e33eff8Schristos return ptr; 81*8e33eff8Schristos 82*8e33eff8Schristos return handleOOM(size, IsNoExcept); 83*8e33eff8Schristos } 84*8e33eff8Schristos 85*8e33eff8Schristos void * 86*8e33eff8Schristos operator new(std::size_t size) { 87*8e33eff8Schristos return newImpl<false>(size); 88*8e33eff8Schristos } 89*8e33eff8Schristos 90*8e33eff8Schristos void * 91*8e33eff8Schristos operator new[](std::size_t size) { 92*8e33eff8Schristos return newImpl<false>(size); 93*8e33eff8Schristos } 94*8e33eff8Schristos 95*8e33eff8Schristos void * 96*8e33eff8Schristos operator new(std::size_t size, const std::nothrow_t &) noexcept { 97*8e33eff8Schristos return newImpl<true>(size); 98*8e33eff8Schristos } 99*8e33eff8Schristos 100*8e33eff8Schristos void * 101*8e33eff8Schristos operator new[](std::size_t size, const std::nothrow_t &) noexcept { 102*8e33eff8Schristos return newImpl<true>(size); 103*8e33eff8Schristos } 104*8e33eff8Schristos 105*8e33eff8Schristos void 106*8e33eff8Schristos operator delete(void *ptr) noexcept { 107*8e33eff8Schristos je_free(ptr); 108*8e33eff8Schristos } 109*8e33eff8Schristos 110*8e33eff8Schristos void 111*8e33eff8Schristos operator delete[](void *ptr) noexcept { 112*8e33eff8Schristos je_free(ptr); 113*8e33eff8Schristos } 114*8e33eff8Schristos 115*8e33eff8Schristos void 116*8e33eff8Schristos operator delete(void *ptr, const std::nothrow_t &) noexcept { 117*8e33eff8Schristos je_free(ptr); 118*8e33eff8Schristos } 119*8e33eff8Schristos 120*8e33eff8Schristos void operator delete[](void *ptr, const std::nothrow_t &) noexcept { 121*8e33eff8Schristos je_free(ptr); 122*8e33eff8Schristos } 123*8e33eff8Schristos 124*8e33eff8Schristos #if __cpp_sized_deallocation >= 201309 125*8e33eff8Schristos 126*8e33eff8Schristos void 127*8e33eff8Schristos operator delete(void *ptr, std::size_t size) noexcept { 128*8e33eff8Schristos if (unlikely(ptr == nullptr)) { 129*8e33eff8Schristos return; 130*8e33eff8Schristos } 131*8e33eff8Schristos je_sdallocx(ptr, size, /*flags=*/0); 132*8e33eff8Schristos } 133*8e33eff8Schristos 134*8e33eff8Schristos void operator delete[](void *ptr, std::size_t size) noexcept { 135*8e33eff8Schristos if (unlikely(ptr == nullptr)) { 136*8e33eff8Schristos return; 137*8e33eff8Schristos } 138*8e33eff8Schristos je_sdallocx(ptr, size, /*flags=*/0); 139*8e33eff8Schristos } 140*8e33eff8Schristos 141*8e33eff8Schristos #endif // __cpp_sized_deallocation 142