| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: sw=4 ts=4 et :
- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #ifndef mozilla_mozalloc_h
- #define mozilla_mozalloc_h
- /*
- * https://bugzilla.mozilla.org/show_bug.cgi?id=427099
- */
- #if defined(__cplusplus)
- # include <new>
- // Since libstdc++ 6, including the C headers (e.g. stdlib.h) instead of the
- // corresponding C++ header (e.g. cstdlib) can cause confusion in C++ code
- // using things defined there. Specifically, with stdlib.h, the use of abs()
- // in gfx/graphite2/src/inc/UtfCodec.h somehow ends up picking the wrong abs()
- # include <cstdlib>
- # include <cstring>
- #else
- # include <stdlib.h>
- # include <string.h>
- #endif
- #if defined(__cplusplus)
- #include "mozilla/fallible.h"
- #include "mozilla/mozalloc_abort.h"
- #include "mozilla/TemplateLib.h"
- #endif
- #include "mozilla/Attributes.h"
- #include "mozilla/Types.h"
- #define MOZALLOC_HAVE_XMALLOC
- #if defined(MOZ_ALWAYS_INLINE_EVEN_DEBUG)
- # define MOZALLOC_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG
- #elif defined(HAVE_FORCEINLINE)
- # define MOZALLOC_INLINE __forceinline
- #else
- # define MOZALLOC_INLINE inline
- #endif
- /* Workaround build problem with Sun Studio 12 */
- #if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
- # undef MOZ_MUST_USE
- # define MOZ_MUST_USE
- # undef MOZ_ALLOCATOR
- # define MOZ_ALLOCATOR
- #endif
- #if defined(__cplusplus)
- extern "C" {
- #endif /* ifdef __cplusplus */
- /*
- * We need to use malloc_impl and free_impl in this file when they are
- * defined, because of how mozglue.dll is linked on Windows, where using
- * malloc/free would end up using the symbols from the MSVCRT instead of
- * ours.
- */
- #ifndef free_impl
- #define free_impl free
- #define free_impl_
- #endif
- #ifndef malloc_impl
- #define malloc_impl malloc
- #define malloc_impl_
- #endif
- /*
- * Each declaration below is analogous to a "standard" allocation
- * function, except that the out-of-memory handling is made explicit.
- * The |moz_x| versions will never return a NULL pointer; if memory
- * is exhausted, they abort. The |moz_| versions may return NULL
- * pointers if memory is exhausted: their return value must be checked.
- *
- * All these allocation functions are *guaranteed* to return a pointer
- * to memory allocated in such a way that that memory can be freed by
- * passing that pointer to |free()|.
- */
- MFBT_API void* moz_xmalloc(size_t size)
- MOZ_ALLOCATOR;
- MFBT_API void* moz_xcalloc(size_t nmemb, size_t size)
- MOZ_ALLOCATOR;
- MFBT_API void* moz_xrealloc(void* ptr, size_t size)
- MOZ_ALLOCATOR;
- MFBT_API char* moz_xstrdup(const char* str)
- MOZ_ALLOCATOR;
- MFBT_API size_t moz_malloc_usable_size(void *ptr);
- MFBT_API size_t moz_malloc_size_of(const void *ptr);
- #if defined(HAVE_STRNDUP)
- MFBT_API char* moz_xstrndup(const char* str, size_t strsize)
- MOZ_ALLOCATOR;
- #endif /* if defined(HAVE_STRNDUP) */
- #if defined(HAVE_POSIX_MEMALIGN)
- MFBT_API MOZ_MUST_USE
- int moz_xposix_memalign(void **ptr, size_t alignment, size_t size);
- MFBT_API MOZ_MUST_USE
- int moz_posix_memalign(void **ptr, size_t alignment, size_t size);
- #endif /* if defined(HAVE_POSIX_MEMALIGN) */
- #if defined(HAVE_MEMALIGN)
- MFBT_API void* moz_xmemalign(size_t boundary, size_t size)
- MOZ_ALLOCATOR;
- #endif /* if defined(HAVE_MEMALIGN) */
- #if defined(HAVE_VALLOC)
- MFBT_API void* moz_xvalloc(size_t size)
- MOZ_ALLOCATOR;
- #endif /* if defined(HAVE_VALLOC) */
- #ifdef __cplusplus
- } /* extern "C" */
- #endif /* ifdef __cplusplus */
- #ifdef __cplusplus
- /*
- * We implement the default operators new/delete as part of
- * libmozalloc, replacing their definitions in libstdc++. The
- * operator new* definitions in libmozalloc will never return a NULL
- * pointer.
- *
- * Each operator new immediately below returns a pointer to memory
- * that can be delete'd by any of
- *
- * (1) the matching infallible operator delete immediately below
- * (2) the matching "fallible" operator delete further below
- * (3) the matching system |operator delete(void*, std::nothrow)|
- * (4) the matching system |operator delete(void*) throw(std::bad_alloc)|
- *
- * NB: these are declared |throw(std::bad_alloc)|, though they will never
- * throw that exception. This declaration is consistent with the rule
- * that |::operator new() throw(std::bad_alloc)| will never return NULL.
- */
- /* NB: This is defined just to silence vacuous warnings about symbol
- * visibility on OS X/gcc. These symbols are force-inline and not
- * exported. */
- #if defined(XP_MACOSX)
- # define MOZALLOC_EXPORT_NEW MFBT_API
- #else
- # define MOZALLOC_EXPORT_NEW
- #endif
- #if defined(ANDROID)
- /*
- * It's important to always specify 'throw()' in GCC because it's used to tell
- * GCC that 'new' may return null. That makes GCC null-check the result before
- * potentially initializing the memory to zero.
- * Also, the Android minimalistic headers don't include std::bad_alloc.
- */
- #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
- #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
- #elif defined(_MSC_VER)
- /*
- * Suppress build warning spam (bug 578546).
- */
- #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS
- #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
- #else
- #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
- #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS throw(std::bad_alloc)
- #endif
- #define MOZALLOC_THROW_BAD_ALLOC MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
- MOZALLOC_EXPORT_NEW
- #if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
- /* gcc's asan somehow doesn't like always_inline on this function. */
- __attribute__((gnu_inline)) inline
- #else
- MOZALLOC_INLINE
- #endif
- void* operator new(size_t size) MOZALLOC_THROW_BAD_ALLOC
- {
- return moz_xmalloc(size);
- }
- MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
- void* operator new(size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
- {
- return malloc_impl(size);
- }
- MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
- void* operator new[](size_t size) MOZALLOC_THROW_BAD_ALLOC
- {
- return moz_xmalloc(size);
- }
- MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
- void* operator new[](size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
- {
- return malloc_impl(size);
- }
- MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
- void operator delete(void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
- {
- return free_impl(ptr);
- }
- MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
- void operator delete(void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
- {
- return free_impl(ptr);
- }
- MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
- void operator delete[](void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
- {
- return free_impl(ptr);
- }
- MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
- void operator delete[](void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
- {
- return free_impl(ptr);
- }
- /*
- * We also add a new allocator variant: "fallible operator new."
- * Unlike libmozalloc's implementations of the standard nofail
- * allocators, this allocator is allowed to return NULL. It can be used
- * as follows
- *
- * Foo* f = new (mozilla::fallible) Foo(...);
- *
- * operator delete(fallible) is defined for completeness only.
- *
- * Each operator new below returns a pointer to memory that can be
- * delete'd by any of
- *
- * (1) the matching "fallible" operator delete below
- * (2) the matching infallible operator delete above
- * (3) the matching system |operator delete(void*, std::nothrow)|
- * (4) the matching system |operator delete(void*) throw(std::bad_alloc)|
- */
- MOZALLOC_INLINE
- void* operator new(size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
- {
- return malloc_impl(size);
- }
- MOZALLOC_INLINE
- void* operator new[](size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
- {
- return malloc_impl(size);
- }
- MOZALLOC_INLINE
- void operator delete(void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
- {
- free_impl(ptr);
- }
- MOZALLOC_INLINE
- void operator delete[](void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
- {
- free_impl(ptr);
- }
- /*
- * This policy is identical to MallocAllocPolicy, except it uses
- * moz_xmalloc/moz_xcalloc/moz_xrealloc instead of
- * malloc/calloc/realloc.
- */
- class InfallibleAllocPolicy
- {
- public:
- template <typename T>
- T* maybe_pod_malloc(size_t aNumElems)
- {
- return pod_malloc<T>(aNumElems);
- }
- template <typename T>
- T* maybe_pod_calloc(size_t aNumElems)
- {
- return pod_calloc<T>(aNumElems);
- }
- template <typename T>
- T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
- {
- return pod_realloc<T>(aPtr, aOldSize, aNewSize);
- }
- template <typename T>
- T* pod_malloc(size_t aNumElems)
- {
- if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
- reportAllocOverflow();
- }
- return static_cast<T*>(moz_xmalloc(aNumElems * sizeof(T)));
- }
- template <typename T>
- T* pod_calloc(size_t aNumElems)
- {
- return static_cast<T*>(moz_xcalloc(aNumElems, sizeof(T)));
- }
- template <typename T>
- T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
- {
- if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
- reportAllocOverflow();
- }
- return static_cast<T*>(moz_xrealloc(aPtr, aNewSize * sizeof(T)));
- }
- void free_(void* aPtr)
- {
- free_impl(aPtr);
- }
- void reportAllocOverflow() const
- {
- mozalloc_abort("alloc overflow");
- }
- bool checkSimulatedOOM() const
- {
- return true;
- }
- };
- #endif /* ifdef __cplusplus */
- #ifdef malloc_impl_
- #undef malloc_impl_
- #undef malloc_impl
- #endif
- #ifdef free_impl_
- #undef free_impl_
- #undef free_impl
- #endif
- #endif /* ifndef mozilla_mozalloc_h */
|