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