]>
Commit | Line | Data |
---|---|---|
b37bf2e1 | 1 | /* |
f9bf01c6 | 2 | * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. |
b37bf2e1 A |
3 | * |
4 | * This library is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU Library General Public | |
6 | * License as published by the Free Software Foundation; either | |
7 | * version 2 of the License, or (at your option) any later version. | |
8 | * | |
9 | * This library is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * Library General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU Library General Public License | |
15 | * along with this library; see the file COPYING.LIB. If not, write to | |
16 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
17 | * Boston, MA 02110-1301, USA. | |
18 | * | |
19 | */ | |
20 | ||
21 | #ifndef WTF_FastMalloc_h | |
22 | #define WTF_FastMalloc_h | |
23 | ||
24 | #include "Platform.h" | |
f9bf01c6 | 25 | #include "PossiblyNull.h" |
b37bf2e1 A |
26 | #include <stdlib.h> |
27 | #include <new> | |
28 | ||
29 | namespace WTF { | |
30 | ||
9dae56ea | 31 | // These functions call CRASH() if an allocation fails. |
f9bf01c6 A |
32 | void* fastMalloc(size_t); |
33 | void* fastZeroedMalloc(size_t); | |
34 | void* fastCalloc(size_t numElements, size_t elementSize); | |
35 | void* fastRealloc(void*, size_t); | |
36 | char* fastStrDup(const char*); | |
4e4e5a6f | 37 | size_t fastMallocSize(const void*); |
f9bf01c6 A |
38 | |
39 | struct TryMallocReturnValue { | |
40 | TryMallocReturnValue(void* data) | |
41 | : m_data(data) | |
42 | { | |
43 | } | |
44 | TryMallocReturnValue(const TryMallocReturnValue& source) | |
45 | : m_data(source.m_data) | |
46 | { | |
47 | source.m_data = 0; | |
48 | } | |
49 | ~TryMallocReturnValue() { ASSERT(!m_data); } | |
50 | template <typename T> bool getValue(T& data) WARN_UNUSED_RETURN; | |
51 | template <typename T> operator PossiblyNull<T>() | |
52 | { | |
53 | T value; | |
54 | getValue(value); | |
55 | return PossiblyNull<T>(value); | |
56 | } | |
57 | private: | |
58 | mutable void* m_data; | |
59 | }; | |
60 | ||
61 | template <typename T> bool TryMallocReturnValue::getValue(T& data) | |
62 | { | |
63 | union u { void* data; T target; } res; | |
64 | res.data = m_data; | |
65 | data = res.target; | |
66 | bool returnValue = !!m_data; | |
67 | m_data = 0; | |
68 | return returnValue; | |
69 | } | |
9dae56ea | 70 | |
f9bf01c6 A |
71 | TryMallocReturnValue tryFastMalloc(size_t n); |
72 | TryMallocReturnValue tryFastZeroedMalloc(size_t n); | |
73 | TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size); | |
74 | TryMallocReturnValue tryFastRealloc(void* p, size_t n); | |
9dae56ea | 75 | |
f9bf01c6 | 76 | void fastFree(void*); |
b37bf2e1 A |
77 | |
78 | #ifndef NDEBUG | |
79 | void fastMallocForbid(); | |
80 | void fastMallocAllow(); | |
81 | #endif | |
82 | ||
f4e78d34 | 83 | void releaseFastMallocFreeMemory(); |
9dae56ea A |
84 | |
85 | struct FastMallocStatistics { | |
4e4e5a6f A |
86 | size_t reservedVMBytes; |
87 | size_t committedVMBytes; | |
88 | size_t freeListBytes; | |
9dae56ea A |
89 | }; |
90 | FastMallocStatistics fastMallocStatistics(); | |
f4e78d34 | 91 | |
ba379fdc A |
92 | // This defines a type which holds an unsigned integer and is the same |
93 | // size as the minimally aligned memory allocation. | |
94 | typedef unsigned long long AllocAlignmentInteger; | |
95 | ||
96 | namespace Internal { | |
97 | enum AllocType { // Start with an unusual number instead of zero, because zero is common. | |
98 | AllocTypeMalloc = 0x375d6750, // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc. | |
99 | AllocTypeClassNew, // Encompasses class operator new from FastAllocBase. | |
100 | AllocTypeClassNewArray, // Encompasses class operator new[] from FastAllocBase. | |
101 | AllocTypeFastNew, // Encompasses fastNew. | |
102 | AllocTypeFastNewArray, // Encompasses fastNewArray. | |
103 | AllocTypeNew, // Encompasses global operator new. | |
104 | AllocTypeNewArray // Encompasses global operator new[]. | |
105 | }; | |
14957cd0 A |
106 | |
107 | enum { | |
108 | ValidationPrefix = 0xf00df00d, | |
109 | ValidationSuffix = 0x0badf00d | |
110 | }; | |
111 | ||
112 | typedef unsigned ValidationTag; | |
113 | ||
114 | struct ValidationHeader { | |
115 | AllocType m_type; | |
116 | unsigned m_size; | |
117 | ValidationTag m_prefix; | |
118 | unsigned m_alignment; | |
119 | }; | |
120 | ||
121 | static const int ValidationBufferSize = sizeof(ValidationHeader) + sizeof(ValidationTag); | |
ba379fdc A |
122 | } |
123 | ||
14957cd0 | 124 | #if ENABLE(WTF_MALLOC_VALIDATION) |
ba379fdc A |
125 | |
126 | // Malloc validation is a scheme whereby a tag is attached to an | |
127 | // allocation which identifies how it was originally allocated. | |
128 | // This allows us to verify that the freeing operation matches the | |
129 | // allocation operation. If memory is allocated with operator new[] | |
130 | // but freed with free or delete, this system would detect that. | |
131 | // In the implementation here, the tag is an integer prepended to | |
132 | // the allocation memory which is assigned one of the AllocType | |
133 | // enumeration values. An alternative implementation of this | |
134 | // scheme could store the tag somewhere else or ignore it. | |
135 | // Users of FastMalloc don't need to know or care how this tagging | |
136 | // is implemented. | |
137 | ||
138 | namespace Internal { | |
14957cd0 A |
139 | |
140 | // Handle a detected alloc/free mismatch. By default this calls CRASH(). | |
141 | void fastMallocMatchFailed(void* p); | |
ba379fdc | 142 | |
14957cd0 | 143 | inline ValidationHeader* fastMallocValidationHeader(void* p) |
ba379fdc | 144 | { |
14957cd0 | 145 | return reinterpret_cast<ValidationHeader*>(static_cast<char*>(p) - sizeof(ValidationHeader)); |
ba379fdc A |
146 | } |
147 | ||
14957cd0 A |
148 | inline ValidationTag* fastMallocValidationSuffix(void* p) |
149 | { | |
150 | ValidationHeader* header = fastMallocValidationHeader(p); | |
151 | if (header->m_prefix != static_cast<unsigned>(ValidationPrefix)) | |
152 | fastMallocMatchFailed(p); | |
153 | ||
154 | return reinterpret_cast<ValidationTag*>(static_cast<char*>(p) + header->m_size); | |
155 | } | |
156 | ||
157 | // Return the AllocType tag associated with the allocated block p. | |
158 | inline AllocType fastMallocMatchValidationType(void* p) | |
ba379fdc | 159 | { |
14957cd0 | 160 | return fastMallocValidationHeader(p)->m_type; |
ba379fdc A |
161 | } |
162 | ||
163 | // Set the AllocType tag to be associaged with the allocated block p. | |
164 | inline void setFastMallocMatchValidationType(void* p, AllocType allocType) | |
165 | { | |
14957cd0 | 166 | fastMallocValidationHeader(p)->m_type = allocType; |
ba379fdc A |
167 | } |
168 | ||
ba379fdc A |
169 | } // namespace Internal |
170 | ||
171 | // This is a higher level function which is used by FastMalloc-using code. | |
172 | inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType) | |
173 | { | |
174 | if (!p) | |
175 | return; | |
176 | ||
177 | Internal::setFastMallocMatchValidationType(p, allocType); | |
178 | } | |
179 | ||
180 | // This is a higher level function which is used by FastMalloc-using code. | |
14957cd0 | 181 | inline void fastMallocMatchValidateFree(void* p, Internal::AllocType) |
ba379fdc A |
182 | { |
183 | if (!p) | |
184 | return; | |
14957cd0 A |
185 | |
186 | Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p); | |
187 | if (header->m_prefix != static_cast<unsigned>(Internal::ValidationPrefix)) | |
188 | Internal::fastMallocMatchFailed(p); | |
ba379fdc | 189 | |
14957cd0 | 190 | if (*Internal::fastMallocValidationSuffix(p) != Internal::ValidationSuffix) |
ba379fdc | 191 | Internal::fastMallocMatchFailed(p); |
14957cd0 | 192 | |
ba379fdc A |
193 | Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc); // Set it to this so that fastFree thinks it's OK. |
194 | } | |
195 | ||
14957cd0 A |
196 | inline void fastMallocValidate(void* p) |
197 | { | |
198 | if (!p) | |
199 | return; | |
200 | ||
201 | Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p); | |
202 | if (header->m_prefix != static_cast<unsigned>(Internal::ValidationPrefix)) | |
203 | Internal::fastMallocMatchFailed(p); | |
204 | ||
205 | if (*Internal::fastMallocValidationSuffix(p) != Internal::ValidationSuffix) | |
206 | Internal::fastMallocMatchFailed(p); | |
207 | } | |
208 | ||
ba379fdc A |
209 | #else |
210 | ||
211 | inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType) | |
212 | { | |
213 | } | |
214 | ||
215 | inline void fastMallocMatchValidateFree(void*, Internal::AllocType) | |
216 | { | |
217 | } | |
218 | ||
219 | #endif | |
220 | ||
b37bf2e1 A |
221 | } // namespace WTF |
222 | ||
b37bf2e1 | 223 | using WTF::fastCalloc; |
4e4e5a6f A |
224 | using WTF::fastFree; |
225 | using WTF::fastMalloc; | |
226 | using WTF::fastMallocSize; | |
b37bf2e1 | 227 | using WTF::fastRealloc; |
4e4e5a6f A |
228 | using WTF::fastStrDup; |
229 | using WTF::fastZeroedMalloc; | |
9dae56ea | 230 | using WTF::tryFastCalloc; |
4e4e5a6f | 231 | using WTF::tryFastMalloc; |
9dae56ea | 232 | using WTF::tryFastRealloc; |
4e4e5a6f | 233 | using WTF::tryFastZeroedMalloc; |
b37bf2e1 A |
234 | |
235 | #ifndef NDEBUG | |
236 | using WTF::fastMallocForbid; | |
237 | using WTF::fastMallocAllow; | |
238 | #endif | |
239 | ||
f9bf01c6 | 240 | #if COMPILER(GCC) && OS(DARWIN) |
b37bf2e1 A |
241 | #define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline)) |
242 | #elif COMPILER(GCC) | |
243 | #define WTF_PRIVATE_INLINE inline __attribute__((always_inline)) | |
f9bf01c6 | 244 | #elif COMPILER(MSVC) || COMPILER(RVCT) |
b37bf2e1 A |
245 | #define WTF_PRIVATE_INLINE __forceinline |
246 | #else | |
247 | #define WTF_PRIVATE_INLINE inline | |
248 | #endif | |
249 | ||
14957cd0 | 250 | #if !defined(_CRTDBG_MAP_ALLOC) && !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC && !PLATFORM(BREWMP)) |
f9bf01c6 A |
251 | |
252 | // The nothrow functions here are actually not all that helpful, because fastMalloc will | |
253 | // call CRASH() rather than returning 0, and returning 0 is what nothrow is all about. | |
254 | // But since WebKit code never uses exceptions or nothrow at all, this is probably OK. | |
255 | // Long term we will adopt FastAllocBase.h everywhere, and and replace this with | |
256 | // debug-only code to make sure we don't use the system malloc via the default operator | |
257 | // new by accident. | |
b37bf2e1 | 258 | |
4e4e5a6f | 259 | #if ENABLE(GLOBAL_FASTMALLOC_NEW) |
ba379fdc | 260 | |
f9bf01c6 A |
261 | #if COMPILER(MSVC) |
262 | #pragma warning(push) | |
263 | #pragma warning(disable: 4290) // Disable the C++ exception specification ignored warning. | |
264 | #endif | |
265 | WTF_PRIVATE_INLINE void* operator new(size_t size) throw (std::bad_alloc) { return fastMalloc(size); } | |
266 | WTF_PRIVATE_INLINE void* operator new(size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } | |
267 | WTF_PRIVATE_INLINE void operator delete(void* p) throw() { fastFree(p); } | |
ba379fdc | 268 | WTF_PRIVATE_INLINE void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); } |
f9bf01c6 A |
269 | WTF_PRIVATE_INLINE void* operator new[](size_t size) throw (std::bad_alloc) { return fastMalloc(size); } |
270 | WTF_PRIVATE_INLINE void* operator new[](size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } | |
271 | WTF_PRIVATE_INLINE void operator delete[](void* p) throw() { fastFree(p); } | |
ba379fdc | 272 | WTF_PRIVATE_INLINE void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); } |
f9bf01c6 A |
273 | #if COMPILER(MSVC) |
274 | #pragma warning(pop) | |
ba379fdc | 275 | #endif |
f9bf01c6 | 276 | |
b37bf2e1 A |
277 | #endif |
278 | ||
f9bf01c6 | 279 | #endif |
b37bf2e1 A |
280 | |
281 | #endif /* WTF_FastMalloc_h */ |