diff -r 000000000000 -r 6474c204b198 memory/mozalloc/mozalloc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memory/mozalloc/mozalloc.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,229 @@ +/* -*- 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/. */ + +#include +#include // for std::bad_alloc +#include + +#include + +#if defined(MALLOC_H) +# include MALLOC_H // for memalign, valloc, malloc_size, malloc_usable_size +#endif // if defined(MALLOC_H) +#include // for size_t +#include // for malloc, free +#if defined(XP_UNIX) +# include // for valloc on *BSD +#endif //if defined(XP_UNIX) + +#if defined(XP_WIN) +# define MOZALLOC_EXPORT __declspec(dllexport) +#endif + +#include "mozilla/mozalloc.h" +#include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom + +/* Windows doesn't have malloc_usable_size, but jemalloc has */ +#if defined(MOZ_MEMORY_WINDOWS) +extern "C" size_t malloc_usable_size(const void *ptr); +#endif + +#ifdef __GNUC__ +#define LIKELY(x) (__builtin_expect(!!(x), 1)) +#define UNLIKELY(x) (__builtin_expect(!!(x), 0)) +#else +#define LIKELY(x) (x) +#define UNLIKELY(x) (x) +#endif + +void +moz_free(void* ptr) +{ + free(ptr); +} + +void* +moz_xmalloc(size_t size) +{ + void* ptr = malloc(size); + if (UNLIKELY(!ptr && size)) { + mozalloc_handle_oom(size); + return moz_xmalloc(size); + } + return ptr; +} +void* +moz_malloc(size_t size) +{ + return malloc(size); +} + +void* +moz_xcalloc(size_t nmemb, size_t size) +{ + void* ptr = calloc(nmemb, size); + if (UNLIKELY(!ptr && nmemb && size)) { + mozalloc_handle_oom(size); + return moz_xcalloc(nmemb, size); + } + return ptr; +} +void* +moz_calloc(size_t nmemb, size_t size) +{ + return calloc(nmemb, size); +} + +void* +moz_xrealloc(void* ptr, size_t size) +{ + void* newptr = realloc(ptr, size); + if (UNLIKELY(!newptr && size)) { + mozalloc_handle_oom(size); + return moz_xrealloc(ptr, size); + } + return newptr; +} +void* +moz_realloc(void* ptr, size_t size) +{ + return realloc(ptr, size); +} + +char* +moz_xstrdup(const char* str) +{ + char* dup = strdup(str); + if (UNLIKELY(!dup)) { + mozalloc_handle_oom(0); + return moz_xstrdup(str); + } + return dup; +} +char* +moz_strdup(const char* str) +{ + return strdup(str); +} + +#if defined(HAVE_STRNDUP) +char* +moz_xstrndup(const char* str, size_t strsize) +{ + char* dup = strndup(str, strsize); + if (UNLIKELY(!dup)) { + mozalloc_handle_oom(strsize); + return moz_xstrndup(str, strsize); + } + return dup; +} +char* +moz_strndup(const char* str, size_t strsize) +{ + return strndup(str, strsize); +} +#endif // if defined(HAVE_STRNDUP) + +#if defined(HAVE_POSIX_MEMALIGN) +int +moz_xposix_memalign(void **ptr, size_t alignment, size_t size) +{ + int err = posix_memalign(ptr, alignment, size); + if (UNLIKELY(err && ENOMEM == err)) { + mozalloc_handle_oom(size); + return moz_xposix_memalign(ptr, alignment, size); + } + // else: (0 == err) or (EINVAL == err) + return err; +} +int +moz_posix_memalign(void **ptr, size_t alignment, size_t size) +{ + int code = posix_memalign(ptr, alignment, size); + if (code) + return code; + +#if defined(XP_MACOSX) + // Workaround faulty OSX posix_memalign, which provides memory with the + // incorrect alignment sometimes, but returns 0 as if nothing was wrong. + size_t mask = alignment - 1; + if (((size_t)(*ptr) & mask) != 0) { + void* old = *ptr; + code = moz_posix_memalign(ptr, alignment, size); + free(old); + } +#endif + + return code; + +} +#endif // if defined(HAVE_POSIX_MEMALIGN) + +#if defined(HAVE_MEMALIGN) +void* +moz_xmemalign(size_t boundary, size_t size) +{ + void* ptr = memalign(boundary, size); + if (UNLIKELY(!ptr && EINVAL != errno)) { + mozalloc_handle_oom(size); + return moz_xmemalign(boundary, size); + } + // non-NULL ptr or errno == EINVAL + return ptr; +} +void* +moz_memalign(size_t boundary, size_t size) +{ + return memalign(boundary, size); +} +#endif // if defined(HAVE_MEMALIGN) + +#if defined(HAVE_VALLOC) +void* +moz_xvalloc(size_t size) +{ + void* ptr = valloc(size); + if (UNLIKELY(!ptr)) { + mozalloc_handle_oom(size); + return moz_xvalloc(size); + } + return ptr; +} +void* +moz_valloc(size_t size) +{ + return valloc(size); +} +#endif // if defined(HAVE_VALLOC) + +size_t +moz_malloc_usable_size(void *ptr) +{ + if (!ptr) + return 0; + +#if defined(XP_MACOSX) + return malloc_size(ptr); +#elif defined(HAVE_MALLOC_USABLE_SIZE) || defined(MOZ_MEMORY) + return malloc_usable_size(ptr); +#elif defined(XP_WIN) + return _msize(ptr); +#else + return 0; +#endif +} + +size_t moz_malloc_size_of(const void *ptr) +{ + return moz_malloc_usable_size((void *)ptr); +} + +namespace mozilla { + +const fallible_t fallible = fallible_t(); + +} // namespace mozilla