mozalloc.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * vim: sw=4 ts=4 et :
  3. */
  4. /* This Source Code Form is subject to the terms of the Mozilla Public
  5. * License, v. 2.0. If a copy of the MPL was not distributed with this
  6. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  7. #ifndef mozilla_mozalloc_h
  8. #define mozilla_mozalloc_h
  9. /*
  10. * https://bugzilla.mozilla.org/show_bug.cgi?id=427099
  11. */
  12. #if defined(__cplusplus)
  13. # include <new>
  14. // Since libstdc++ 6, including the C headers (e.g. stdlib.h) instead of the
  15. // corresponding C++ header (e.g. cstdlib) can cause confusion in C++ code
  16. // using things defined there. Specifically, with stdlib.h, the use of abs()
  17. // in gfx/graphite2/src/inc/UtfCodec.h somehow ends up picking the wrong abs()
  18. # include <cstdlib>
  19. # include <cstring>
  20. #else
  21. # include <stdlib.h>
  22. # include <string.h>
  23. #endif
  24. #if defined(__cplusplus)
  25. #include "mozilla/fallible.h"
  26. #include "mozilla/mozalloc_abort.h"
  27. #include "mozilla/TemplateLib.h"
  28. #endif
  29. #include "mozilla/Attributes.h"
  30. #include "mozilla/Types.h"
  31. #define MOZALLOC_HAVE_XMALLOC
  32. #if defined(MOZ_ALWAYS_INLINE_EVEN_DEBUG)
  33. # define MOZALLOC_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG
  34. #elif defined(HAVE_FORCEINLINE)
  35. # define MOZALLOC_INLINE __forceinline
  36. #else
  37. # define MOZALLOC_INLINE inline
  38. #endif
  39. /* Workaround build problem with Sun Studio 12 */
  40. #if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
  41. # undef MOZ_MUST_USE
  42. # define MOZ_MUST_USE
  43. # undef MOZ_ALLOCATOR
  44. # define MOZ_ALLOCATOR
  45. #endif
  46. #if defined(__cplusplus)
  47. extern "C" {
  48. #endif /* ifdef __cplusplus */
  49. /*
  50. * We need to use malloc_impl and free_impl in this file when they are
  51. * defined, because of how mozglue.dll is linked on Windows, where using
  52. * malloc/free would end up using the symbols from the MSVCRT instead of
  53. * ours.
  54. */
  55. #ifndef free_impl
  56. #define free_impl free
  57. #define free_impl_
  58. #endif
  59. #ifndef malloc_impl
  60. #define malloc_impl malloc
  61. #define malloc_impl_
  62. #endif
  63. /*
  64. * Each declaration below is analogous to a "standard" allocation
  65. * function, except that the out-of-memory handling is made explicit.
  66. * The |moz_x| versions will never return a NULL pointer; if memory
  67. * is exhausted, they abort. The |moz_| versions may return NULL
  68. * pointers if memory is exhausted: their return value must be checked.
  69. *
  70. * All these allocation functions are *guaranteed* to return a pointer
  71. * to memory allocated in such a way that that memory can be freed by
  72. * passing that pointer to |free()|.
  73. */
  74. MFBT_API void* moz_xmalloc(size_t size)
  75. MOZ_ALLOCATOR;
  76. MFBT_API void* moz_xcalloc(size_t nmemb, size_t size)
  77. MOZ_ALLOCATOR;
  78. MFBT_API void* moz_xrealloc(void* ptr, size_t size)
  79. MOZ_ALLOCATOR;
  80. MFBT_API char* moz_xstrdup(const char* str)
  81. MOZ_ALLOCATOR;
  82. MFBT_API size_t moz_malloc_usable_size(void *ptr);
  83. MFBT_API size_t moz_malloc_size_of(const void *ptr);
  84. #if defined(HAVE_STRNDUP)
  85. MFBT_API char* moz_xstrndup(const char* str, size_t strsize)
  86. MOZ_ALLOCATOR;
  87. #endif /* if defined(HAVE_STRNDUP) */
  88. #if defined(HAVE_POSIX_MEMALIGN)
  89. MFBT_API MOZ_MUST_USE
  90. int moz_xposix_memalign(void **ptr, size_t alignment, size_t size);
  91. MFBT_API MOZ_MUST_USE
  92. int moz_posix_memalign(void **ptr, size_t alignment, size_t size);
  93. #endif /* if defined(HAVE_POSIX_MEMALIGN) */
  94. #if defined(HAVE_MEMALIGN)
  95. MFBT_API void* moz_xmemalign(size_t boundary, size_t size)
  96. MOZ_ALLOCATOR;
  97. #endif /* if defined(HAVE_MEMALIGN) */
  98. #if defined(HAVE_VALLOC)
  99. MFBT_API void* moz_xvalloc(size_t size)
  100. MOZ_ALLOCATOR;
  101. #endif /* if defined(HAVE_VALLOC) */
  102. #ifdef __cplusplus
  103. } /* extern "C" */
  104. #endif /* ifdef __cplusplus */
  105. #ifdef __cplusplus
  106. /*
  107. * We implement the default operators new/delete as part of
  108. * libmozalloc, replacing their definitions in libstdc++. The
  109. * operator new* definitions in libmozalloc will never return a NULL
  110. * pointer.
  111. *
  112. * Each operator new immediately below returns a pointer to memory
  113. * that can be delete'd by any of
  114. *
  115. * (1) the matching infallible operator delete immediately below
  116. * (2) the matching "fallible" operator delete further below
  117. * (3) the matching system |operator delete(void*, std::nothrow)|
  118. * (4) the matching system |operator delete(void*) throw(std::bad_alloc)|
  119. *
  120. * NB: these are declared |throw(std::bad_alloc)|, though they will never
  121. * throw that exception. This declaration is consistent with the rule
  122. * that |::operator new() throw(std::bad_alloc)| will never return NULL.
  123. */
  124. /* NB: This is defined just to silence vacuous warnings about symbol
  125. * visibility on OS X/gcc. These symbols are force-inline and not
  126. * exported. */
  127. #if defined(XP_MACOSX)
  128. # define MOZALLOC_EXPORT_NEW MFBT_API
  129. #else
  130. # define MOZALLOC_EXPORT_NEW
  131. #endif
  132. #if defined(ANDROID)
  133. /*
  134. * It's important to always specify 'throw()' in GCC because it's used to tell
  135. * GCC that 'new' may return null. That makes GCC null-check the result before
  136. * potentially initializing the memory to zero.
  137. * Also, the Android minimalistic headers don't include std::bad_alloc.
  138. */
  139. #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
  140. #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
  141. #elif defined(_MSC_VER)
  142. /*
  143. * Suppress build warning spam (bug 578546).
  144. */
  145. #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS
  146. #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
  147. #else
  148. #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
  149. #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS throw(std::bad_alloc)
  150. #endif
  151. #define MOZALLOC_THROW_BAD_ALLOC MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
  152. MOZALLOC_EXPORT_NEW
  153. #if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
  154. /* gcc's asan somehow doesn't like always_inline on this function. */
  155. __attribute__((gnu_inline)) inline
  156. #else
  157. MOZALLOC_INLINE
  158. #endif
  159. void* operator new(size_t size) MOZALLOC_THROW_BAD_ALLOC
  160. {
  161. return moz_xmalloc(size);
  162. }
  163. MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
  164. void* operator new(size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
  165. {
  166. return malloc_impl(size);
  167. }
  168. MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
  169. void* operator new[](size_t size) MOZALLOC_THROW_BAD_ALLOC
  170. {
  171. return moz_xmalloc(size);
  172. }
  173. MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
  174. void* operator new[](size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
  175. {
  176. return malloc_impl(size);
  177. }
  178. MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
  179. void operator delete(void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
  180. {
  181. return free_impl(ptr);
  182. }
  183. MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
  184. void operator delete(void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
  185. {
  186. return free_impl(ptr);
  187. }
  188. MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
  189. void operator delete[](void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
  190. {
  191. return free_impl(ptr);
  192. }
  193. MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
  194. void operator delete[](void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
  195. {
  196. return free_impl(ptr);
  197. }
  198. /*
  199. * We also add a new allocator variant: "fallible operator new."
  200. * Unlike libmozalloc's implementations of the standard nofail
  201. * allocators, this allocator is allowed to return NULL. It can be used
  202. * as follows
  203. *
  204. * Foo* f = new (mozilla::fallible) Foo(...);
  205. *
  206. * operator delete(fallible) is defined for completeness only.
  207. *
  208. * Each operator new below returns a pointer to memory that can be
  209. * delete'd by any of
  210. *
  211. * (1) the matching "fallible" operator delete below
  212. * (2) the matching infallible operator delete above
  213. * (3) the matching system |operator delete(void*, std::nothrow)|
  214. * (4) the matching system |operator delete(void*) throw(std::bad_alloc)|
  215. */
  216. MOZALLOC_INLINE
  217. void* operator new(size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
  218. {
  219. return malloc_impl(size);
  220. }
  221. MOZALLOC_INLINE
  222. void* operator new[](size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
  223. {
  224. return malloc_impl(size);
  225. }
  226. MOZALLOC_INLINE
  227. void operator delete(void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
  228. {
  229. free_impl(ptr);
  230. }
  231. MOZALLOC_INLINE
  232. void operator delete[](void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
  233. {
  234. free_impl(ptr);
  235. }
  236. /*
  237. * This policy is identical to MallocAllocPolicy, except it uses
  238. * moz_xmalloc/moz_xcalloc/moz_xrealloc instead of
  239. * malloc/calloc/realloc.
  240. */
  241. class InfallibleAllocPolicy
  242. {
  243. public:
  244. template <typename T>
  245. T* maybe_pod_malloc(size_t aNumElems)
  246. {
  247. return pod_malloc<T>(aNumElems);
  248. }
  249. template <typename T>
  250. T* maybe_pod_calloc(size_t aNumElems)
  251. {
  252. return pod_calloc<T>(aNumElems);
  253. }
  254. template <typename T>
  255. T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
  256. {
  257. return pod_realloc<T>(aPtr, aOldSize, aNewSize);
  258. }
  259. template <typename T>
  260. T* pod_malloc(size_t aNumElems)
  261. {
  262. if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
  263. reportAllocOverflow();
  264. }
  265. return static_cast<T*>(moz_xmalloc(aNumElems * sizeof(T)));
  266. }
  267. template <typename T>
  268. T* pod_calloc(size_t aNumElems)
  269. {
  270. return static_cast<T*>(moz_xcalloc(aNumElems, sizeof(T)));
  271. }
  272. template <typename T>
  273. T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
  274. {
  275. if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
  276. reportAllocOverflow();
  277. }
  278. return static_cast<T*>(moz_xrealloc(aPtr, aNewSize * sizeof(T)));
  279. }
  280. void free_(void* aPtr)
  281. {
  282. free_impl(aPtr);
  283. }
  284. void reportAllocOverflow() const
  285. {
  286. mozalloc_abort("alloc overflow");
  287. }
  288. bool checkSimulatedOOM() const
  289. {
  290. return true;
  291. }
  292. };
  293. #endif /* ifdef __cplusplus */
  294. #ifdef malloc_impl_
  295. #undef malloc_impl_
  296. #undef malloc_impl
  297. #endif
  298. #ifdef free_impl_
  299. #undef free_impl_
  300. #undef free_impl
  301. #endif
  302. #endif /* ifndef mozilla_mozalloc_h */