/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: sw=2 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 // for size_t #if defined(MOZ_MEMORY) // mozalloc.cpp is part of the same library as mozmemory, thus MOZ_MEMORY_IMPL // is needed. #define MOZ_MEMORY_IMPL #include "mozmemory_wrap.h" #if defined(XP_DARWIN) #include // for malloc_size #endif // See mozmemory_wrap.h for more details. This file is part of libmozglue, so // it needs to use _impl suffixes. However, with libmozglue growing, this is // becoming cumbersome, so we will likely use a malloc.h wrapper of some sort // and allow the use of the functions without a _impl suffix. #define MALLOC_DECL(name, return_type, ...) \ MOZ_MEMORY_API return_type name##_impl(__VA_ARGS__); #define MALLOC_FUNCS MALLOC_FUNCS_MALLOC #include "malloc_decls.h" MOZ_MEMORY_API char* strdup_impl(const char*); MOZ_MEMORY_API char* strndup_impl(const char*, size_t); #else // When jemalloc is disabled, or when building the static runtime variant, // we need not to use the suffixes. #if defined(MALLOC_H) #include MALLOC_H // for memalign, malloc_size, malloc_us #endif // if defined(MALLOC_H) #include // for malloc, free #if defined(XP_UNIX) #include #endif // if defined(XP_UNIX) #define malloc_impl malloc #define calloc_impl calloc #define realloc_impl realloc #define free_impl free #define memalign_impl memalign #define malloc_usable_size_impl malloc_usable_size #define strdup_impl strdup #define strndup_impl strndup #endif #include #include // for std::bad_alloc #include #include #include "mozilla/Assertions.h" #include "mozilla/CheckedInt.h" #include "mozilla/Likely.h" #include "mozilla/mozalloc.h" #include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom void* moz_xmalloc(size_t size) { void* ptr = malloc_impl(size); if (MOZ_UNLIKELY(!ptr && size)) { mozalloc_handle_oom(size); return moz_xmalloc(size); } return ptr; } void* moz_xcalloc(size_t nmemb, size_t size) { void* ptr = calloc_impl(nmemb, size); if (MOZ_UNLIKELY(!ptr && nmemb && size)) { mozilla::CheckedInt totalSize = mozilla::CheckedInt(nmemb) * size; mozalloc_handle_oom(totalSize.isValid() ? totalSize.value() : SIZE_MAX); return moz_xcalloc(nmemb, size); } return ptr; } void* moz_xrealloc(void* ptr, size_t size) { void* newptr = realloc_impl(ptr, size); if (MOZ_UNLIKELY(!newptr && size)) { mozalloc_handle_oom(size); return moz_xrealloc(ptr, size); } return newptr; } char* moz_xstrdup(const char* str) { char* dup = strdup_impl(str); if (MOZ_UNLIKELY(!dup)) { mozalloc_handle_oom(0); return moz_xstrdup(str); } return dup; } #if defined(HAVE_STRNDUP) char* moz_xstrndup(const char* str, size_t strsize) { char* dup = strndup_impl(str, strsize); if (MOZ_UNLIKELY(!dup)) { mozalloc_handle_oom(strsize); return moz_xstrndup(str, strsize); } return dup; } #endif // if defined(HAVE_STRNDUP) void* moz_xmemdup(const void* ptr, size_t size) { void* newPtr = moz_xmalloc(size); memcpy(newPtr, ptr, size); return newPtr; } #ifndef HAVE_MEMALIGN // We always have a definition of memalign, but system headers don't // necessarily come with a declaration. extern "C" void* memalign(size_t, size_t); #endif void* moz_xmemalign(size_t boundary, size_t size) { void* ptr = memalign_impl(boundary, size); if (MOZ_UNLIKELY(!ptr && EINVAL != errno)) { mozalloc_handle_oom(size); return moz_xmemalign(boundary, size); } // non-NULL ptr or errno == EINVAL return ptr; } size_t moz_malloc_usable_size(void* ptr) { if (!ptr) return 0; #if defined(XP_DARWIN) return malloc_size(ptr); #elif defined(HAVE_MALLOC_USABLE_SIZE) || defined(MOZ_MEMORY) return malloc_usable_size_impl(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); } #if defined(MOZ_MEMORY) #include "mozjemalloc_types.h" // mozmemory.h declares jemalloc_ptr_info(), but including that header in this // file is complicated. So we just redeclare it here instead, and include // mozjemalloc_types.h for jemalloc_ptr_info_t. MOZ_JEMALLOC_API void jemalloc_ptr_info(const void* ptr, jemalloc_ptr_info_t* info); #endif size_t moz_malloc_enclosing_size_of(const void* ptr) { #if defined(MOZ_MEMORY) jemalloc_ptr_info_t info; jemalloc_ptr_info(ptr, &info); return jemalloc_ptr_is_live(&info) ? info.size : 0; #else return 0; #endif }