mozalloc.cpp (4226B)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: sw=2 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 8 #include <stddef.h> // for size_t 9 10 #if defined(MALLOC_H) 11 # include MALLOC_H // for memalign, malloc_size, malloc_us 12 #endif // if defined(MALLOC_H) 13 14 #if !defined(MOZ_MEMORY) 15 // When jemalloc is disabled, or when building the static runtime variant, 16 // we need not to use the suffixes. 17 18 # include <stdlib.h> // for malloc, free 19 # if defined(XP_UNIX) 20 # include <unistd.h> 21 # endif // if defined(XP_UNIX) 22 23 # define malloc_impl malloc 24 # define calloc_impl calloc 25 # define realloc_impl realloc 26 # define free_impl free 27 # define memalign_impl memalign 28 # define malloc_usable_size_impl malloc_usable_size 29 # define strdup_impl strdup 30 # define strndup_impl strndup 31 32 #endif 33 34 #include <errno.h> 35 #include <new> // for std::bad_alloc 36 #include <cstring> 37 38 #include <sys/types.h> 39 40 #include "mozilla/CheckedInt.h" 41 #include "mozilla/Likely.h" 42 #include "mozilla/mozalloc.h" 43 #include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom 44 45 #if defined(MOZ_MEMORY) 46 MOZ_MEMORY_API char* strdup_impl(const char*); 47 MOZ_MEMORY_API char* strndup_impl(const char*, size_t); 48 #endif 49 50 void* moz_xmalloc(size_t size) { 51 void* ptr = malloc_impl(size); 52 if (MOZ_UNLIKELY(!ptr && size)) { 53 mozalloc_handle_oom(size); 54 return moz_xmalloc(size); 55 } 56 return ptr; 57 } 58 59 void* moz_xcalloc(size_t nmemb, size_t size) { 60 void* ptr = calloc_impl(nmemb, size); 61 if (MOZ_UNLIKELY(!ptr && nmemb && size)) { 62 mozilla::CheckedInt<size_t> totalSize = 63 mozilla::CheckedInt<size_t>(nmemb) * size; 64 mozalloc_handle_oom(totalSize.isValid() ? totalSize.value() : SIZE_MAX); 65 return moz_xcalloc(nmemb, size); 66 } 67 return ptr; 68 } 69 70 void* moz_xrealloc(void* ptr, size_t size) { 71 void* newptr = realloc_impl(ptr, size); 72 if (MOZ_UNLIKELY(!newptr && size)) { 73 mozalloc_handle_oom(size); 74 return moz_xrealloc(ptr, size); 75 } 76 return newptr; 77 } 78 79 char* moz_xstrdup(const char* str) { 80 char* dup = strdup_impl(str); 81 if (MOZ_UNLIKELY(!dup)) { 82 mozalloc_handle_oom(0); 83 return moz_xstrdup(str); 84 } 85 return dup; 86 } 87 88 #if defined(HAVE_STRNDUP) 89 char* moz_xstrndup(const char* str, size_t strsize) { 90 char* dup = strndup_impl(str, strsize); 91 if (MOZ_UNLIKELY(!dup)) { 92 mozalloc_handle_oom(strsize); 93 return moz_xstrndup(str, strsize); 94 } 95 return dup; 96 } 97 #endif // if defined(HAVE_STRNDUP) 98 99 void* moz_xmemdup(const void* ptr, size_t size) { 100 void* newPtr = moz_xmalloc(size); 101 memcpy(newPtr, ptr, size); 102 return newPtr; 103 } 104 105 #ifndef __wasm__ 106 # ifndef HAVE_MEMALIGN 107 // We always have a definition of memalign, but system headers don't 108 // necessarily come with a declaration. 109 extern "C" void* memalign(size_t, size_t); 110 # endif 111 112 void* moz_xmemalign(size_t boundary, size_t size) { 113 void* ptr = memalign_impl(boundary, size); 114 if (MOZ_UNLIKELY(!ptr && EINVAL != errno)) { 115 mozalloc_handle_oom(size); 116 return moz_xmemalign(boundary, size); 117 } 118 // non-NULL ptr or errno == EINVAL 119 return ptr; 120 } 121 #endif 122 123 size_t moz_malloc_usable_size(void* ptr) { 124 if (!ptr) return 0; 125 126 #if defined(XP_DARWIN) 127 return malloc_size(ptr); 128 #elif defined(HAVE_MALLOC_USABLE_SIZE) || defined(MOZ_MEMORY) 129 return malloc_usable_size_impl(ptr); 130 #elif defined(XP_WIN) 131 return _msize(ptr); 132 #else 133 return 0; 134 #endif 135 } 136 137 size_t moz_malloc_size_of(const void* ptr) { 138 return moz_malloc_usable_size((void*)ptr); 139 } 140 141 #if defined(MOZ_MEMORY) 142 # include "mozjemalloc_types.h" 143 // mozmemory.h declares jemalloc_ptr_info(), but including that header in this 144 // file is complicated. So we just redeclare it here instead, and include 145 // mozjemalloc_types.h for jemalloc_ptr_info_t. 146 MOZ_JEMALLOC_API void jemalloc_ptr_info(const void* ptr, 147 jemalloc_ptr_info_t* info); 148 #endif 149 150 size_t moz_malloc_enclosing_size_of(const void* ptr) { 151 #if defined(MOZ_MEMORY) 152 jemalloc_ptr_info_t info; 153 jemalloc_ptr_info(ptr, &info); 154 return jemalloc_ptr_is_live(&info) ? info.size : 0; 155 #else 156 return 0; 157 #endif 158 }