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