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