xref: /freebsd/contrib/jemalloc/src/jemalloc_cpp.cpp (revision b5daf675efc746611c7cfcd1fa474b8905064c4b)
1 <<<<<<< HEAD
2 #include <mutex>
3 #include <new>
4 
5 #define JEMALLOC_CPP_CPP_
6 #ifdef __cplusplus
7 extern "C" {
8 #endif
9 
10 #include "jemalloc/internal/jemalloc_preamble.h"
11 #include "jemalloc/internal/jemalloc_internal_includes.h"
12 
13 #ifdef __cplusplus
14 }
15 #endif
16 
17 // All operators in this file are exported.
18 
19 // Possibly alias hidden versions of malloc and sdallocx to avoid an extra plt
20 // thunk?
21 //
22 // extern __typeof (sdallocx) sdallocx_int
23 //  __attribute ((alias ("sdallocx"),
24 //		visibility ("hidden")));
25 //
26 // ... but it needs to work with jemalloc namespaces.
27 
28 void	*operator new(std::size_t size);
29 void	*operator new[](std::size_t size);
30 void	*operator new(std::size_t size, const std::nothrow_t &) noexcept;
31 void	*operator new[](std::size_t size, const std::nothrow_t &) noexcept;
32 void	operator delete(void *ptr) noexcept;
33 void	operator delete[](void *ptr) noexcept;
34 void	operator delete(void *ptr, const std::nothrow_t &) noexcept;
35 void	operator delete[](void *ptr, const std::nothrow_t &) noexcept;
36 
37 #if __cpp_sized_deallocation >= 201309
38 /* C++14's sized-delete operators. */
39 void	operator delete(void *ptr, std::size_t size) noexcept;
40 void	operator delete[](void *ptr, std::size_t size) noexcept;
41 #endif
42 
43 #if __cpp_aligned_new >= 201606
44 /* C++17's over-aligned operators. */
45 void	*operator new(std::size_t size, std::align_val_t);
46 void	*operator new(std::size_t size, std::align_val_t, const std::nothrow_t &) noexcept;
47 void	*operator new[](std::size_t size, std::align_val_t);
48 void	*operator new[](std::size_t size, std::align_val_t, const std::nothrow_t &) noexcept;
49 void	operator delete(void* ptr, std::align_val_t) noexcept;
50 void	operator delete(void* ptr, std::align_val_t, const std::nothrow_t &) noexcept;
51 void	operator delete(void* ptr, std::size_t size, std::align_val_t al) noexcept;
52 void	operator delete[](void* ptr, std::align_val_t) noexcept;
53 void	operator delete[](void* ptr, std::align_val_t, const std::nothrow_t &) noexcept;
54 void	operator delete[](void* ptr, std::size_t size, std::align_val_t al) noexcept;
55 #endif
56 
57 JEMALLOC_NOINLINE
58 static void *
59 handleOOM(std::size_t size, bool nothrow) {
60 	if (opt_experimental_infallible_new) {
61 		safety_check_fail("<jemalloc>: Allocation failed and "
62 		    "opt.experimental_infallible_new is true. Aborting.\n");
63 		return nullptr;
64 	}
65 
66 	void *ptr = nullptr;
67 
68 	while (ptr == nullptr) {
69 		std::new_handler handler;
70 		// GCC-4.8 and clang 4.0 do not have std::get_new_handler.
71 		{
72 			static std::mutex mtx;
73 			std::lock_guard<std::mutex> lock(mtx);
74 
75 			handler = std::set_new_handler(nullptr);
76 			std::set_new_handler(handler);
77 		}
78 		if (handler == nullptr)
79 			break;
80 
81 		try {
82 			handler();
83 		} catch (const std::bad_alloc &) {
84 			break;
85 		}
86 
87 		ptr = je_malloc(size);
88 	}
89 
90 	if (ptr == nullptr && !nothrow)
91 		std::__throw_bad_alloc();
92 	return ptr;
93 }
94 
95 template <bool IsNoExcept>
96 JEMALLOC_NOINLINE
97 static void *
98 fallback_impl(std::size_t size) noexcept(IsNoExcept) {
99 	void *ptr = malloc_default(size);
100 	if (likely(ptr != nullptr)) {
101 		return ptr;
102 	}
103 	return handleOOM(size, IsNoExcept);
104 }
105 
106 template <bool IsNoExcept>
107 JEMALLOC_ALWAYS_INLINE
108 void *
109 newImpl(std::size_t size) noexcept(IsNoExcept) {
110 	return imalloc_fastpath(size, &fallback_impl<IsNoExcept>);
111 }
112 
113 void *
114 operator new(std::size_t size) {
115 	return newImpl<false>(size);
116 }
117 
118 void *
119 operator new[](std::size_t size) {
120 	return newImpl<false>(size);
121 }
122 
123 void *
124 operator new(std::size_t size, const std::nothrow_t &) noexcept {
125 	return newImpl<true>(size);
126 }
127 
128 void *
129 operator new[](std::size_t size, const std::nothrow_t &) noexcept {
130 	return newImpl<true>(size);
131 }
132 
133 #if __cpp_aligned_new >= 201606
134 
135 template <bool IsNoExcept>
136 JEMALLOC_ALWAYS_INLINE
137 void *
138 alignedNewImpl(std::size_t size, std::align_val_t alignment) noexcept(IsNoExcept) {
139 	void *ptr = je_aligned_alloc(static_cast<std::size_t>(alignment), size);
140 	if (likely(ptr != nullptr)) {
141 		return ptr;
142 	}
143 
144 	return handleOOM(size, IsNoExcept);
145 }
146 
147 void *
148 operator new(std::size_t size, std::align_val_t alignment) {
149 	return alignedNewImpl<false>(size, alignment);
150 }
151 
152 void *
153 operator new[](std::size_t size, std::align_val_t alignment) {
154 	return alignedNewImpl<false>(size, alignment);
155 }
156 
157 void *
158 operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t &) noexcept {
159 	return alignedNewImpl<true>(size, alignment);
160 }
161 
162 void *
163 operator new[](std::size_t size, std::align_val_t alignment, const std::nothrow_t &) noexcept {
164 	return alignedNewImpl<true>(size, alignment);
165 }
166 
167 #endif  // __cpp_aligned_new
168 
169 void
170 operator delete(void *ptr) noexcept {
171 	je_free(ptr);
172 }
173 
174 void
175 operator delete[](void *ptr) noexcept {
176 	je_free(ptr);
177 }
178 
179 void
180 operator delete(void *ptr, const std::nothrow_t &) noexcept {
181 	je_free(ptr);
182 }
183 
184 void operator delete[](void *ptr, const std::nothrow_t &) noexcept {
185 	je_free(ptr);
186 }
187 
188 #if __cpp_sized_deallocation >= 201309
189 
190 JEMALLOC_ALWAYS_INLINE
191 void
192 sizedDeleteImpl(void* ptr, std::size_t size) noexcept {
193 	if (unlikely(ptr == nullptr)) {
194 		return;
195 	}
196 	je_sdallocx_noflags(ptr, size);
197 }
198 
199 void
200 operator delete(void *ptr, std::size_t size) noexcept {
201 	sizedDeleteImpl(ptr, size);
202 }
203 
204 void
205 operator delete[](void *ptr, std::size_t size) noexcept {
206 	sizedDeleteImpl(ptr, size);
207 }
208 
209 #endif  // __cpp_sized_deallocation
210 
211 #if __cpp_aligned_new >= 201606
212 
213 JEMALLOC_ALWAYS_INLINE
214 void
215 alignedSizedDeleteImpl(void* ptr, std::size_t size, std::align_val_t alignment) noexcept {
216 	if (config_debug) {
217 		assert(((size_t)alignment & ((size_t)alignment - 1)) == 0);
218 	}
219 	if (unlikely(ptr == nullptr)) {
220 		return;
221 	}
222 	je_sdallocx(ptr, size, MALLOCX_ALIGN(alignment));
223 }
224 
225 void
226 operator delete(void* ptr, std::align_val_t) noexcept {
227 	je_free(ptr);
228 }
229 
230 void
231 operator delete[](void* ptr, std::align_val_t) noexcept {
232 	je_free(ptr);
233 }
234 
235 void
236 operator delete(void* ptr, std::align_val_t, const std::nothrow_t&) noexcept {
237 	je_free(ptr);
238 }
239 
240 void
241 operator delete[](void* ptr, std::align_val_t, const std::nothrow_t&) noexcept {
242 	je_free(ptr);
243 }
244 
245 void
246 operator delete(void* ptr, std::size_t size, std::align_val_t alignment) noexcept {
247 	alignedSizedDeleteImpl(ptr, size, alignment);
248 }
249 
250 void
251 operator delete[](void* ptr, std::size_t size, std::align_val_t alignment) noexcept {
252 	alignedSizedDeleteImpl(ptr, size, alignment);
253 }
254 
255 #endif  // __cpp_aligned_new
256 ||||||| dec341af7695
257 =======
258 #include <mutex>
259 #include <new>
260 
261 #define JEMALLOC_CPP_CPP_
262 #ifdef __cplusplus
263 extern "C" {
264 #endif
265 
266 #include "jemalloc/internal/jemalloc_preamble.h"
267 #include "jemalloc/internal/jemalloc_internal_includes.h"
268 
269 #ifdef __cplusplus
270 }
271 #endif
272 
273 // All operators in this file are exported.
274 
275 // Possibly alias hidden versions of malloc and sdallocx to avoid an extra plt
276 // thunk?
277 //
278 // extern __typeof (sdallocx) sdallocx_int
279 //  __attribute ((alias ("sdallocx"),
280 //		visibility ("hidden")));
281 //
282 // ... but it needs to work with jemalloc namespaces.
283 
284 void	*operator new(std::size_t size);
285 void	*operator new[](std::size_t size);
286 void	*operator new(std::size_t size, const std::nothrow_t &) noexcept;
287 void	*operator new[](std::size_t size, const std::nothrow_t &) noexcept;
288 void	operator delete(void *ptr) noexcept;
289 void	operator delete[](void *ptr) noexcept;
290 void	operator delete(void *ptr, const std::nothrow_t &) noexcept;
291 void	operator delete[](void *ptr, const std::nothrow_t &) noexcept;
292 
293 #if __cpp_sized_deallocation >= 201309
294 /* C++14's sized-delete operators. */
295 void	operator delete(void *ptr, std::size_t size) noexcept;
296 void	operator delete[](void *ptr, std::size_t size) noexcept;
297 #endif
298 
299 JEMALLOC_NOINLINE
300 static void *
301 handleOOM(std::size_t size, bool nothrow) {
302 	void *ptr = nullptr;
303 
304 	while (ptr == nullptr) {
305 		std::new_handler handler;
306 		// GCC-4.8 and clang 4.0 do not have std::get_new_handler.
307 		{
308 			static std::mutex mtx;
309 			std::lock_guard<std::mutex> lock(mtx);
310 
311 			handler = std::set_new_handler(nullptr);
312 			std::set_new_handler(handler);
313 		}
314 		if (handler == nullptr)
315 			break;
316 
317 		try {
318 			handler();
319 		} catch (const std::bad_alloc &) {
320 			break;
321 		}
322 
323 		ptr = je_malloc(size);
324 	}
325 
326 	if (ptr == nullptr && !nothrow)
327 		std::__throw_bad_alloc();
328 	return ptr;
329 }
330 
331 template <bool IsNoExcept>
332 JEMALLOC_ALWAYS_INLINE
333 void *
334 newImpl(std::size_t size) noexcept(IsNoExcept) {
335 	void *ptr = je_malloc(size);
336 	if (likely(ptr != nullptr))
337 		return ptr;
338 
339 	return handleOOM(size, IsNoExcept);
340 }
341 
342 void *
343 operator new(std::size_t size) {
344 	return newImpl<false>(size);
345 }
346 
347 void *
348 operator new[](std::size_t size) {
349 	return newImpl<false>(size);
350 }
351 
352 void *
353 operator new(std::size_t size, const std::nothrow_t &) noexcept {
354 	return newImpl<true>(size);
355 }
356 
357 void *
358 operator new[](std::size_t size, const std::nothrow_t &) noexcept {
359 	return newImpl<true>(size);
360 }
361 
362 void
363 operator delete(void *ptr) noexcept {
364 	je_free(ptr);
365 }
366 
367 void
368 operator delete[](void *ptr) noexcept {
369 	je_free(ptr);
370 }
371 
372 void
373 operator delete(void *ptr, const std::nothrow_t &) noexcept {
374 	je_free(ptr);
375 }
376 
377 void operator delete[](void *ptr, const std::nothrow_t &) noexcept {
378 	je_free(ptr);
379 }
380 
381 #if __cpp_sized_deallocation >= 201309
382 
383 void
384 operator delete(void *ptr, std::size_t size) noexcept {
385 	if (unlikely(ptr == nullptr)) {
386 		return;
387 	}
388 	je_sdallocx_noflags(ptr, size);
389 }
390 
391 void operator delete[](void *ptr, std::size_t size) noexcept {
392 	if (unlikely(ptr == nullptr)) {
393 		return;
394 	}
395 	je_sdallocx_noflags(ptr, size);
396 }
397 
398 #endif  // __cpp_sized_deallocation
399 >>>>>>> main
400