/src/mozilla-central/memory/mozalloc/mozalloc.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
2 | | * vim: sw=4 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(MOZ_MEMORY) |
11 | | // mozalloc.cpp is part of the same library as mozmemory, thus MOZ_MEMORY_IMPL |
12 | | // is needed. |
13 | | #define MOZ_MEMORY_IMPL |
14 | | #include "mozmemory_wrap.h" |
15 | | |
16 | | #if defined(XP_DARWIN) |
17 | | #include <malloc/malloc.h> // for malloc_size |
18 | | #endif |
19 | | |
20 | | // See mozmemory_wrap.h for more details. This file is part of libmozglue, so |
21 | | // it needs to use _impl suffixes. However, with libmozglue growing, this is |
22 | | // becoming cumbersome, so we will likely use a malloc.h wrapper of some sort |
23 | | // and allow the use of the functions without a _impl suffix. |
24 | | #define MALLOC_DECL(name, return_type, ...) \ |
25 | | MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__); |
26 | | #define MALLOC_FUNCS MALLOC_FUNCS_MALLOC |
27 | | #include "malloc_decls.h" |
28 | | |
29 | | MOZ_MEMORY_API char *strdup_impl(const char *); |
30 | | MOZ_MEMORY_API char *strndup_impl(const char *, size_t); |
31 | | |
32 | | #else |
33 | | // When jemalloc is disabled, or when building the static runtime variant, |
34 | | // we need not to use the suffixes. |
35 | | |
36 | | #if defined(MALLOC_H) |
37 | | # include MALLOC_H // for memalign, malloc_size, malloc_us |
38 | | #endif // if defined(MALLOC_H) |
39 | | #include <stdlib.h> // for malloc, free |
40 | | #if defined(XP_UNIX) |
41 | | # include <unistd.h> |
42 | | #endif //if defined(XP_UNIX) |
43 | | |
44 | 21.6M | #define malloc_impl malloc |
45 | 19 | #define calloc_impl calloc |
46 | 33.8k | #define realloc_impl realloc |
47 | | #define free_impl free |
48 | 0 | #define memalign_impl memalign |
49 | 4.99k | #define malloc_usable_size_impl malloc_usable_size |
50 | 1.65k | #define strdup_impl strdup |
51 | 0 | #define strndup_impl strndup |
52 | | |
53 | | #endif |
54 | | |
55 | | #include <errno.h> |
56 | | #include <new> // for std::bad_alloc |
57 | | #include <cstring> |
58 | | |
59 | | #include <sys/types.h> |
60 | | |
61 | | #include "mozilla/Assertions.h" |
62 | | #include "mozilla/CheckedInt.h" |
63 | | #include "mozilla/Likely.h" |
64 | | #include "mozilla/mozalloc.h" |
65 | | #include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom |
66 | | |
67 | | void* |
68 | | moz_xmalloc(size_t size) |
69 | 21.6M | { |
70 | 21.6M | void* ptr = malloc_impl(size); |
71 | 21.6M | if (MOZ_UNLIKELY(!ptr && size)) { |
72 | 0 | mozalloc_handle_oom(size); |
73 | 0 | return moz_xmalloc(size); |
74 | 0 | } |
75 | 21.6M | return ptr; |
76 | 21.6M | } |
77 | | |
78 | | void* |
79 | | moz_xcalloc(size_t nmemb, size_t size) |
80 | 19 | { |
81 | 19 | void* ptr = calloc_impl(nmemb, size); |
82 | 19 | if (MOZ_UNLIKELY(!ptr && nmemb && size)) { |
83 | 0 | mozilla::CheckedInt<size_t> totalSize = mozilla::CheckedInt<size_t>(nmemb) * size; |
84 | 0 | mozalloc_handle_oom(totalSize.isValid() ? totalSize.value() : SIZE_MAX); |
85 | 0 | return moz_xcalloc(nmemb, size); |
86 | 0 | } |
87 | 19 | return ptr; |
88 | 19 | } |
89 | | |
90 | | void* |
91 | | moz_xrealloc(void* ptr, size_t size) |
92 | 33.8k | { |
93 | 33.8k | void* newptr = realloc_impl(ptr, size); |
94 | 33.8k | if (MOZ_UNLIKELY(!newptr && size)) { |
95 | 0 | mozalloc_handle_oom(size); |
96 | 0 | return moz_xrealloc(ptr, size); |
97 | 0 | } |
98 | 33.8k | return newptr; |
99 | 33.8k | } |
100 | | |
101 | | char* |
102 | | moz_xstrdup(const char* str) |
103 | 1.65k | { |
104 | 1.65k | char* dup = strdup_impl(str); |
105 | 1.65k | if (MOZ_UNLIKELY(!dup)) { |
106 | 0 | mozalloc_handle_oom(0); |
107 | 0 | return moz_xstrdup(str); |
108 | 0 | } |
109 | 1.65k | return dup; |
110 | 1.65k | } |
111 | | |
112 | | #if defined(HAVE_STRNDUP) |
113 | | char* |
114 | | moz_xstrndup(const char* str, size_t strsize) |
115 | 0 | { |
116 | 0 | char* dup = strndup_impl(str, strsize); |
117 | 0 | if (MOZ_UNLIKELY(!dup)) { |
118 | 0 | mozalloc_handle_oom(strsize); |
119 | 0 | return moz_xstrndup(str, strsize); |
120 | 0 | } |
121 | 0 | return dup; |
122 | 0 | } |
123 | | #endif // if defined(HAVE_STRNDUP) |
124 | | |
125 | | void* |
126 | | moz_xmemdup(const void* ptr, size_t size) |
127 | 3 | { |
128 | 3 | void* newPtr = moz_xmalloc(size); |
129 | 3 | memcpy(newPtr, ptr, size); |
130 | 3 | return newPtr; |
131 | 3 | } |
132 | | |
133 | | #ifndef HAVE_MEMALIGN |
134 | | // We always have a definition of memalign, but system headers don't |
135 | | // necessarily come with a declaration. |
136 | | extern "C" void* memalign(size_t, size_t); |
137 | | #endif |
138 | | |
139 | | void* |
140 | | moz_xmemalign(size_t boundary, size_t size) |
141 | 0 | { |
142 | 0 | void* ptr = memalign_impl(boundary, size); |
143 | 0 | if (MOZ_UNLIKELY(!ptr && EINVAL != errno)) { |
144 | 0 | mozalloc_handle_oom(size); |
145 | 0 | return moz_xmemalign(boundary, size); |
146 | 0 | } |
147 | 0 | // non-NULL ptr or errno == EINVAL |
148 | 0 | return ptr; |
149 | 0 | } |
150 | | |
151 | | size_t |
152 | | moz_malloc_usable_size(void *ptr) |
153 | 4.99k | { |
154 | 4.99k | if (!ptr) |
155 | 0 | return 0; |
156 | 4.99k | |
157 | | #if defined(XP_DARWIN) |
158 | | return malloc_size(ptr); |
159 | | #elif defined(HAVE_MALLOC_USABLE_SIZE) || defined(MOZ_MEMORY) |
160 | 4.99k | return malloc_usable_size_impl(ptr); |
161 | | #elif defined(XP_WIN) |
162 | | return _msize(ptr); |
163 | | #else |
164 | | return 0; |
165 | | #endif |
166 | | } |
167 | | |
168 | | size_t |
169 | | moz_malloc_size_of(const void *ptr) |
170 | 4.99k | { |
171 | 4.99k | return moz_malloc_usable_size((void *)ptr); |
172 | 4.99k | } |
173 | | |
174 | | #if defined(MOZ_MEMORY) |
175 | | #include "mozjemalloc_types.h" |
176 | | // mozmemory.h declares jemalloc_ptr_info(), but including that header in this |
177 | | // file is complicated. So we just redeclare it here instead, and include |
178 | | // mozjemalloc_types.h for jemalloc_ptr_info_t. |
179 | | MOZ_JEMALLOC_API void jemalloc_ptr_info(const void* ptr, |
180 | | jemalloc_ptr_info_t* info); |
181 | | #endif |
182 | | |
183 | | size_t |
184 | | moz_malloc_enclosing_size_of(const void *ptr) |
185 | 0 | { |
186 | | #if defined(MOZ_MEMORY) |
187 | | jemalloc_ptr_info_t info; |
188 | | jemalloc_ptr_info(ptr, &info); |
189 | | return jemalloc_ptr_is_live(&info) ? info.size : 0; |
190 | | #else |
191 | | return 0; |
192 | 0 | #endif |
193 | 0 | } |