jemalloc_cpp.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #include <mutex>
  2. #include <new>
  3. #define JEMALLOC_CPP_CPP_
  4. #ifdef __cplusplus
  5. extern "C" {
  6. #endif
  7. #include "jemalloc/internal/jemalloc_preamble.h"
  8. #include "jemalloc/internal/jemalloc_internal_includes.h"
  9. #ifdef __cplusplus
  10. }
  11. #endif
  12. // All operators in this file are exported.
  13. // Possibly alias hidden versions of malloc and sdallocx to avoid an extra plt
  14. // thunk?
  15. //
  16. // extern __typeof (sdallocx) sdallocx_int
  17. // __attribute ((alias ("sdallocx"),
  18. // visibility ("hidden")));
  19. //
  20. // ... but it needs to work with jemalloc namespaces.
  21. void *operator new(std::size_t size);
  22. void *operator new[](std::size_t size);
  23. void *operator new(std::size_t size, const std::nothrow_t &) noexcept;
  24. void *operator new[](std::size_t size, const std::nothrow_t &) noexcept;
  25. void operator delete(void *ptr) noexcept;
  26. void operator delete[](void *ptr) noexcept;
  27. void operator delete(void *ptr, const std::nothrow_t &) noexcept;
  28. void operator delete[](void *ptr, const std::nothrow_t &) noexcept;
  29. #if __cpp_sized_deallocation >= 201309
  30. /* C++14's sized-delete operators. */
  31. void operator delete(void *ptr, std::size_t size) noexcept;
  32. void operator delete[](void *ptr, std::size_t size) noexcept;
  33. #endif
  34. #if __cpp_aligned_new >= 201606
  35. /* C++17's over-aligned operators. */
  36. void *operator new(std::size_t size, std::align_val_t);
  37. void *operator new(std::size_t size, std::align_val_t, const std::nothrow_t &) noexcept;
  38. void *operator new[](std::size_t size, std::align_val_t);
  39. void *operator new[](std::size_t size, std::align_val_t, const std::nothrow_t &) noexcept;
  40. void operator delete(void* ptr, std::align_val_t) noexcept;
  41. void operator delete(void* ptr, std::align_val_t, const std::nothrow_t &) noexcept;
  42. void operator delete(void* ptr, std::size_t size, std::align_val_t al) noexcept;
  43. void operator delete[](void* ptr, std::align_val_t) noexcept;
  44. void operator delete[](void* ptr, std::align_val_t, const std::nothrow_t &) noexcept;
  45. void operator delete[](void* ptr, std::size_t size, std::align_val_t al) noexcept;
  46. #endif
  47. JEMALLOC_NOINLINE
  48. static void *
  49. handleOOM(std::size_t size, bool nothrow) {
  50. if (opt_experimental_infallible_new) {
  51. safety_check_fail("<jemalloc>: Allocation failed and "
  52. "opt.experimental_infallible_new is true. Aborting.\n");
  53. return nullptr;
  54. }
  55. void *ptr = nullptr;
  56. while (ptr == nullptr) {
  57. std::new_handler handler;
  58. // GCC-4.8 and clang 4.0 do not have std::get_new_handler.
  59. {
  60. static std::mutex mtx;
  61. std::lock_guard<std::mutex> lock(mtx);
  62. handler = std::set_new_handler(nullptr);
  63. std::set_new_handler(handler);
  64. }
  65. if (handler == nullptr)
  66. break;
  67. try {
  68. handler();
  69. } catch (const std::bad_alloc &) {
  70. break;
  71. }
  72. ptr = je_malloc(size);
  73. }
  74. if (ptr == nullptr && !nothrow)
  75. std::__throw_bad_alloc();
  76. return ptr;
  77. }
  78. template <bool IsNoExcept>
  79. JEMALLOC_NOINLINE
  80. static void *
  81. fallback_impl(std::size_t size) noexcept(IsNoExcept) {
  82. void *ptr = malloc_default(size);
  83. if (likely(ptr != nullptr)) {
  84. return ptr;
  85. }
  86. return handleOOM(size, IsNoExcept);
  87. }
  88. template <bool IsNoExcept>
  89. JEMALLOC_ALWAYS_INLINE
  90. void *
  91. newImpl(std::size_t size) noexcept(IsNoExcept) {
  92. return imalloc_fastpath(size, &fallback_impl<IsNoExcept>);
  93. }
  94. void *
  95. operator new(std::size_t size) {
  96. return newImpl<false>(size);
  97. }
  98. void *
  99. operator new[](std::size_t size) {
  100. return newImpl<false>(size);
  101. }
  102. void *
  103. operator new(std::size_t size, const std::nothrow_t &) noexcept {
  104. return newImpl<true>(size);
  105. }
  106. void *
  107. operator new[](std::size_t size, const std::nothrow_t &) noexcept {
  108. return newImpl<true>(size);
  109. }
  110. #if __cpp_aligned_new >= 201606
  111. template <bool IsNoExcept>
  112. JEMALLOC_ALWAYS_INLINE
  113. void *
  114. alignedNewImpl(std::size_t size, std::align_val_t alignment) noexcept(IsNoExcept) {
  115. void *ptr = je_aligned_alloc(static_cast<std::size_t>(alignment), size);
  116. if (likely(ptr != nullptr)) {
  117. return ptr;
  118. }
  119. return handleOOM(size, IsNoExcept);
  120. }
  121. void *
  122. operator new(std::size_t size, std::align_val_t alignment) {
  123. return alignedNewImpl<false>(size, alignment);
  124. }
  125. void *
  126. operator new[](std::size_t size, std::align_val_t alignment) {
  127. return alignedNewImpl<false>(size, alignment);
  128. }
  129. void *
  130. operator new(std::size_t size, std::align_val_t alignment, const std::nothrow_t &) noexcept {
  131. return alignedNewImpl<true>(size, alignment);
  132. }
  133. void *
  134. operator new[](std::size_t size, std::align_val_t alignment, const std::nothrow_t &) noexcept {
  135. return alignedNewImpl<true>(size, alignment);
  136. }
  137. #endif // __cpp_aligned_new
  138. void
  139. operator delete(void *ptr) noexcept {
  140. je_free(ptr);
  141. }
  142. void
  143. operator delete[](void *ptr) noexcept {
  144. je_free(ptr);
  145. }
  146. void
  147. operator delete(void *ptr, const std::nothrow_t &) noexcept {
  148. je_free(ptr);
  149. }
  150. void operator delete[](void *ptr, const std::nothrow_t &) noexcept {
  151. je_free(ptr);
  152. }
  153. #if __cpp_sized_deallocation >= 201309
  154. JEMALLOC_ALWAYS_INLINE
  155. void
  156. sizedDeleteImpl(void* ptr, std::size_t size) noexcept {
  157. if (unlikely(ptr == nullptr)) {
  158. return;
  159. }
  160. je_sdallocx_noflags(ptr, size);
  161. }
  162. void
  163. operator delete(void *ptr, std::size_t size) noexcept {
  164. sizedDeleteImpl(ptr, size);
  165. }
  166. void
  167. operator delete[](void *ptr, std::size_t size) noexcept {
  168. sizedDeleteImpl(ptr, size);
  169. }
  170. #endif // __cpp_sized_deallocation
  171. #if __cpp_aligned_new >= 201606
  172. JEMALLOC_ALWAYS_INLINE
  173. void
  174. alignedSizedDeleteImpl(void* ptr, std::size_t size, std::align_val_t alignment) noexcept {
  175. if (config_debug) {
  176. assert(((size_t)alignment & ((size_t)alignment - 1)) == 0);
  177. }
  178. if (unlikely(ptr == nullptr)) {
  179. return;
  180. }
  181. je_sdallocx(ptr, size, MALLOCX_ALIGN(alignment));
  182. }
  183. void
  184. operator delete(void* ptr, std::align_val_t) noexcept {
  185. je_free(ptr);
  186. }
  187. void
  188. operator delete[](void* ptr, std::align_val_t) noexcept {
  189. je_free(ptr);
  190. }
  191. void
  192. operator delete(void* ptr, std::align_val_t, const std::nothrow_t&) noexcept {
  193. je_free(ptr);
  194. }
  195. void
  196. operator delete[](void* ptr, std::align_val_t, const std::nothrow_t&) noexcept {
  197. je_free(ptr);
  198. }
  199. void
  200. operator delete(void* ptr, std::size_t size, std::align_val_t alignment) noexcept {
  201. alignedSizedDeleteImpl(ptr, size, alignment);
  202. }
  203. void
  204. operator delete[](void* ptr, std::size_t size, std::align_val_t alignment) noexcept {
  205. alignedSizedDeleteImpl(ptr, size, alignment);
  206. }
  207. #endif // __cpp_aligned_new