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 *
handleOOM(std::size_t size,bool nothrow)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 *
newImpl(std::size_t size)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 *
operator new(std::size_t size)86 operator new(std::size_t size) {
87 return newImpl<false>(size);
88 }
89
90 void *
operator new[](std::size_t size)91 operator new[](std::size_t size) {
92 return newImpl<false>(size);
93 }
94
95 void *
operator new(std::size_t size,const std::nothrow_t &)96 operator new(std::size_t size, const std::nothrow_t &) noexcept {
97 return newImpl<true>(size);
98 }
99
100 void *
operator new[](std::size_t size,const std::nothrow_t &)101 operator new[](std::size_t size, const std::nothrow_t &) noexcept {
102 return newImpl<true>(size);
103 }
104
105 void
operator delete(void * ptr)106 operator delete(void *ptr) noexcept {
107 je_free(ptr);
108 }
109
110 void
operator delete[](void * ptr)111 operator delete[](void *ptr) noexcept {
112 je_free(ptr);
113 }
114
115 void
operator delete(void * ptr,const std::nothrow_t &)116 operator delete(void *ptr, const std::nothrow_t &) noexcept {
117 je_free(ptr);
118 }
119
operator delete[](void * ptr,const std::nothrow_t &)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
operator delete(void * ptr,std::size_t size)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
operator delete[](void * ptr,std::size_t size)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