michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: sw=4 ts=4 et : michael@0: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_mozalloc_h michael@0: #define mozilla_mozalloc_h michael@0: michael@0: /* michael@0: * https://bugzilla.mozilla.org/show_bug.cgi?id=427099 michael@0: */ michael@0: michael@0: #include michael@0: #include michael@0: #if defined(__cplusplus) michael@0: # include michael@0: #endif michael@0: #include "xpcom-config.h" michael@0: michael@0: #if defined(__cplusplus) michael@0: #include "mozilla/fallible.h" michael@0: #endif michael@0: #include "mozilla/Attributes.h" michael@0: michael@0: #define MOZALLOC_HAVE_XMALLOC michael@0: michael@0: #if defined(MOZALLOC_EXPORT) michael@0: /* do nothing: it's been defined to __declspec(dllexport) by michael@0: * mozalloc*.cpp on platforms where that's required. */ michael@0: #elif defined(XP_WIN) michael@0: # define MOZALLOC_EXPORT __declspec(dllimport) michael@0: #elif defined(HAVE_VISIBILITY_ATTRIBUTE) michael@0: /* Make sure symbols are still exported even if we're wrapped in a michael@0: * |visibility push(hidden)| blanket. */ michael@0: # define MOZALLOC_EXPORT __attribute__ ((visibility ("default"))) michael@0: #else michael@0: # define MOZALLOC_EXPORT michael@0: #endif michael@0: michael@0: michael@0: #if defined(MOZ_ALWAYS_INLINE_EVEN_DEBUG) michael@0: # define MOZALLOC_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG michael@0: #elif defined(HAVE_FORCEINLINE) michael@0: # define MOZALLOC_INLINE __forceinline michael@0: #else michael@0: # define MOZALLOC_INLINE inline michael@0: #endif michael@0: michael@0: /* Workaround build problem with Sun Studio 12 */ michael@0: #if defined(__SUNPRO_C) || defined(__SUNPRO_CC) michael@0: # undef NS_WARN_UNUSED_RESULT michael@0: # define NS_WARN_UNUSED_RESULT michael@0: # undef NS_ATTR_MALLOC michael@0: # define NS_ATTR_MALLOC michael@0: #endif michael@0: michael@0: #if defined(__cplusplus) michael@0: extern "C" { michael@0: #endif /* ifdef __cplusplus */ michael@0: michael@0: michael@0: /* michael@0: * Each pair of declarations below is analogous to a "standard" michael@0: * allocation function, except that the out-of-memory handling is made michael@0: * explicit. The |moz_x| versions will never return a NULL pointer; michael@0: * if memory is exhausted, they abort. The |moz_| versions may return michael@0: * NULL pointers if memory is exhausted: their return value must be michael@0: * checked. michael@0: * michael@0: * All these allocation functions are *guaranteed* to return a pointer michael@0: * to memory allocated in such a way that that memory can be freed by michael@0: * passing that pointer to |moz_free()|. michael@0: */ michael@0: michael@0: MOZALLOC_EXPORT michael@0: void moz_free(void* ptr); michael@0: michael@0: MOZALLOC_EXPORT void* moz_xmalloc(size_t size) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: michael@0: MOZALLOC_EXPORT michael@0: void* moz_malloc(size_t size) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: michael@0: michael@0: MOZALLOC_EXPORT void* moz_xcalloc(size_t nmemb, size_t size) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: michael@0: MOZALLOC_EXPORT void* moz_calloc(size_t nmemb, size_t size) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: michael@0: michael@0: MOZALLOC_EXPORT void* moz_xrealloc(void* ptr, size_t size) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: michael@0: MOZALLOC_EXPORT void* moz_realloc(void* ptr, size_t size) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: michael@0: michael@0: MOZALLOC_EXPORT char* moz_xstrdup(const char* str) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: michael@0: MOZALLOC_EXPORT char* moz_strdup(const char* str) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: michael@0: MOZALLOC_EXPORT size_t moz_malloc_usable_size(void *ptr); michael@0: michael@0: MOZALLOC_EXPORT size_t moz_malloc_size_of(const void *ptr); michael@0: michael@0: #if defined(HAVE_STRNDUP) michael@0: MOZALLOC_EXPORT char* moz_xstrndup(const char* str, size_t strsize) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: michael@0: MOZALLOC_EXPORT char* moz_strndup(const char* str, size_t strsize) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: #endif /* if defined(HAVE_STRNDUP) */ michael@0: michael@0: michael@0: #if defined(HAVE_POSIX_MEMALIGN) michael@0: MOZALLOC_EXPORT int moz_xposix_memalign(void **ptr, size_t alignment, size_t size) michael@0: NS_WARN_UNUSED_RESULT; michael@0: michael@0: MOZALLOC_EXPORT int moz_posix_memalign(void **ptr, size_t alignment, size_t size) michael@0: NS_WARN_UNUSED_RESULT; michael@0: #endif /* if defined(HAVE_POSIX_MEMALIGN) */ michael@0: michael@0: michael@0: #if defined(HAVE_MEMALIGN) michael@0: MOZALLOC_EXPORT void* moz_xmemalign(size_t boundary, size_t size) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: michael@0: MOZALLOC_EXPORT void* moz_memalign(size_t boundary, size_t size) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: #endif /* if defined(HAVE_MEMALIGN) */ michael@0: michael@0: michael@0: #if defined(HAVE_VALLOC) michael@0: MOZALLOC_EXPORT void* moz_xvalloc(size_t size) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: michael@0: MOZALLOC_EXPORT void* moz_valloc(size_t size) michael@0: NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT; michael@0: #endif /* if defined(HAVE_VALLOC) */ michael@0: michael@0: michael@0: #ifdef __cplusplus michael@0: } /* extern "C" */ michael@0: #endif /* ifdef __cplusplus */ michael@0: michael@0: michael@0: #ifdef __cplusplus michael@0: michael@0: /* michael@0: * We implement the default operators new/delete as part of michael@0: * libmozalloc, replacing their definitions in libstdc++. The michael@0: * operator new* definitions in libmozalloc will never return a NULL michael@0: * pointer. michael@0: * michael@0: * Each operator new immediately below returns a pointer to memory michael@0: * that can be delete'd by any of michael@0: * michael@0: * (1) the matching infallible operator delete immediately below michael@0: * (2) the matching "fallible" operator delete further below michael@0: * (3) the matching system |operator delete(void*, std::nothrow)| michael@0: * (4) the matching system |operator delete(void*) throw(std::bad_alloc)| michael@0: * michael@0: * NB: these are declared |throw(std::bad_alloc)|, though they will never michael@0: * throw that exception. This declaration is consistent with the rule michael@0: * that |::operator new() throw(std::bad_alloc)| will never return NULL. michael@0: */ michael@0: michael@0: /* NB: This is defined just to silence vacuous warnings about symbol michael@0: * visibility on OS X/gcc. These symbols are force-inline and not michael@0: * exported. */ michael@0: #if defined(XP_MACOSX) michael@0: # define MOZALLOC_EXPORT_NEW MOZALLOC_EXPORT michael@0: #else michael@0: # define MOZALLOC_EXPORT_NEW michael@0: #endif michael@0: michael@0: #if defined(ANDROID) || defined(_MSC_VER) michael@0: /* michael@0: * Android doesn't fully support exceptions, so its header michael@0: * has operators that don't specify throw() at all. Also include MSVC michael@0: * to suppress build warning spam (bug 578546). michael@0: */ michael@0: #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS /**/ michael@0: #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS michael@0: #else michael@0: #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw() michael@0: #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS throw(std::bad_alloc) michael@0: #endif michael@0: michael@0: #define MOZALLOC_THROW_BAD_ALLOC MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS michael@0: michael@0: MOZALLOC_EXPORT_NEW MOZALLOC_INLINE michael@0: void* operator new(size_t size) MOZALLOC_THROW_BAD_ALLOC michael@0: { michael@0: return moz_xmalloc(size); michael@0: } michael@0: michael@0: MOZALLOC_EXPORT_NEW MOZALLOC_INLINE michael@0: void* operator new(size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS michael@0: { michael@0: return moz_malloc(size); michael@0: } michael@0: michael@0: MOZALLOC_EXPORT_NEW MOZALLOC_INLINE michael@0: void* operator new[](size_t size) MOZALLOC_THROW_BAD_ALLOC michael@0: { michael@0: return moz_xmalloc(size); michael@0: } michael@0: michael@0: MOZALLOC_EXPORT_NEW MOZALLOC_INLINE michael@0: void* operator new[](size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS michael@0: { michael@0: return moz_malloc(size); michael@0: } michael@0: michael@0: MOZALLOC_EXPORT_NEW MOZALLOC_INLINE michael@0: void operator delete(void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS michael@0: { michael@0: return moz_free(ptr); michael@0: } michael@0: michael@0: MOZALLOC_EXPORT_NEW MOZALLOC_INLINE michael@0: void operator delete(void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS michael@0: { michael@0: return moz_free(ptr); michael@0: } michael@0: michael@0: MOZALLOC_EXPORT_NEW MOZALLOC_INLINE michael@0: void operator delete[](void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS michael@0: { michael@0: return moz_free(ptr); michael@0: } michael@0: michael@0: MOZALLOC_EXPORT_NEW MOZALLOC_INLINE michael@0: void operator delete[](void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS michael@0: { michael@0: return moz_free(ptr); michael@0: } michael@0: michael@0: michael@0: /* michael@0: * We also add a new allocator variant: "fallible operator new." michael@0: * Unlike libmozalloc's implementations of the standard nofail michael@0: * allocators, this allocator is allowed to return NULL. It can be used michael@0: * as follows michael@0: * michael@0: * Foo* f = new (mozilla::fallible) Foo(...); michael@0: * michael@0: * operator delete(fallible) is defined for completeness only. michael@0: * michael@0: * Each operator new below returns a pointer to memory that can be michael@0: * delete'd by any of michael@0: * michael@0: * (1) the matching "fallible" operator delete below michael@0: * (2) the matching infallible operator delete above michael@0: * (3) the matching system |operator delete(void*, std::nothrow)| michael@0: * (4) the matching system |operator delete(void*) throw(std::bad_alloc)| michael@0: */ michael@0: michael@0: MOZALLOC_INLINE michael@0: void* operator new(size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS michael@0: { michael@0: return moz_malloc(size); michael@0: } michael@0: michael@0: MOZALLOC_INLINE michael@0: void* operator new[](size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS michael@0: { michael@0: return moz_malloc(size); michael@0: } michael@0: michael@0: MOZALLOC_INLINE michael@0: void operator delete(void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS michael@0: { michael@0: moz_free(ptr); michael@0: } michael@0: michael@0: MOZALLOC_INLINE michael@0: void operator delete[](void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS michael@0: { michael@0: moz_free(ptr); michael@0: } michael@0: michael@0: #endif /* ifdef __cplusplus */ michael@0: michael@0: michael@0: #endif /* ifndef mozilla_mozalloc_h */