]>
Commit | Line | Data |
---|---|---|
ba379fdc A |
1 | /* |
2 | * Copyright (C) 2008, 2009 Paul Pedriana <ppedriana@ea.com>. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of | |
14 | * its contributors may be used to endorse or promote products derived | |
15 | * from this software without specific prior written permission. | |
16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY | |
18 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
20 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY | |
21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | |
28 | ||
29 | #ifndef FastAllocBase_h | |
30 | #define FastAllocBase_h | |
31 | ||
32 | // Provides customizable overrides of fastMalloc/fastFree and operator new/delete | |
33 | // | |
34 | // Provided functionality: | |
35 | // namespace WTF { | |
36 | // class FastAllocBase; | |
37 | // | |
38 | // T* fastNew<T>(); | |
39 | // T* fastNew<T>(arg); | |
40 | // T* fastNew<T>(arg, arg); | |
41 | // T* fastNewArray<T>(count); | |
42 | // void fastDelete(T* p); | |
43 | // void fastDeleteArray(T* p); | |
44 | // void fastNonNullDelete(T* p); | |
45 | // void fastNonNullDeleteArray(T* p); | |
46 | // } | |
47 | // | |
48 | // FastDelete assumes that the underlying | |
49 | // | |
50 | // Example usage: | |
51 | // class Widget : public FastAllocBase { ... }; | |
52 | // | |
53 | // char* charPtr = fastNew<char>(); | |
54 | // fastDelete(charPtr); | |
55 | // | |
56 | // char* charArrayPtr = fastNewArray<char>(37); | |
57 | // fastDeleteArray(charArrayPtr); | |
58 | // | |
59 | // void** voidPtrPtr = fastNew<void*>(); | |
60 | // fastDelete(voidPtrPtr); | |
61 | // | |
62 | // void** voidPtrArrayPtr = fastNewArray<void*>(37); | |
63 | // fastDeleteArray(voidPtrArrayPtr); | |
64 | // | |
65 | // POD* podPtr = fastNew<POD>(); | |
66 | // fastDelete(podPtr); | |
67 | // | |
68 | // POD* podArrayPtr = fastNewArray<POD>(37); | |
69 | // fastDeleteArray(podArrayPtr); | |
70 | // | |
71 | // Object* objectPtr = fastNew<Object>(); | |
72 | // fastDelete(objectPtr); | |
73 | // | |
74 | // Object* objectArrayPtr = fastNewArray<Object>(37); | |
75 | // fastDeleteArray(objectArrayPtr); | |
76 | // | |
77 | ||
78 | #include <new> | |
79 | #include <stdint.h> | |
80 | #include <stdlib.h> | |
81 | #include <string.h> | |
82 | #include "Assertions.h" | |
83 | #include "FastMalloc.h" | |
84 | #include "TypeTraits.h" | |
85 | ||
86 | namespace WTF { | |
87 | ||
88 | class FastAllocBase { | |
89 | public: | |
90 | // Placement operator new. | |
91 | void* operator new(size_t, void* p) { return p; } | |
92 | void* operator new[](size_t, void* p) { return p; } | |
93 | ||
94 | void* operator new(size_t size) | |
95 | { | |
96 | void* p = fastMalloc(size); | |
97 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNew); | |
98 | return p; | |
99 | } | |
100 | ||
101 | void operator delete(void* p) | |
102 | { | |
103 | fastMallocMatchValidateFree(p, Internal::AllocTypeClassNew); | |
104 | fastFree(p); | |
105 | } | |
106 | ||
107 | void* operator new[](size_t size) | |
108 | { | |
109 | void* p = fastMalloc(size); | |
110 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeClassNewArray); | |
111 | return p; | |
112 | } | |
113 | ||
114 | void operator delete[](void* p) | |
115 | { | |
116 | fastMallocMatchValidateFree(p, Internal::AllocTypeClassNewArray); | |
117 | fastFree(p); | |
118 | } | |
119 | }; | |
120 | ||
121 | // fastNew / fastDelete | |
122 | ||
123 | template <typename T> | |
124 | inline T* fastNew() | |
125 | { | |
126 | void* p = fastMalloc(sizeof(T)); | |
127 | ||
128 | if (!p) | |
129 | return 0; | |
130 | ||
131 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); | |
132 | return ::new(p) T; | |
133 | } | |
134 | ||
135 | template <typename T, typename Arg1> | |
136 | inline T* fastNew(Arg1 arg1) | |
137 | { | |
138 | void* p = fastMalloc(sizeof(T)); | |
139 | ||
140 | if (!p) | |
141 | return 0; | |
142 | ||
143 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); | |
144 | return ::new(p) T(arg1); | |
145 | } | |
146 | ||
147 | template <typename T, typename Arg1, typename Arg2> | |
148 | inline T* fastNew(Arg1 arg1, Arg2 arg2) | |
149 | { | |
150 | void* p = fastMalloc(sizeof(T)); | |
151 | ||
152 | if (!p) | |
153 | return 0; | |
154 | ||
155 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); | |
156 | return ::new(p) T(arg1, arg2); | |
157 | } | |
158 | ||
159 | template <typename T, typename Arg1, typename Arg2, typename Arg3> | |
160 | inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3) | |
161 | { | |
162 | void* p = fastMalloc(sizeof(T)); | |
163 | ||
164 | if (!p) | |
165 | return 0; | |
166 | ||
167 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); | |
168 | return ::new(p) T(arg1, arg2, arg3); | |
169 | } | |
170 | ||
171 | template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> | |
172 | inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) | |
173 | { | |
174 | void* p = fastMalloc(sizeof(T)); | |
175 | ||
176 | if (!p) | |
177 | return 0; | |
178 | ||
179 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); | |
180 | return ::new(p) T(arg1, arg2, arg3, arg4); | |
181 | } | |
182 | ||
183 | template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> | |
184 | inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) | |
185 | { | |
186 | void* p = fastMalloc(sizeof(T)); | |
187 | ||
188 | if (!p) | |
189 | return 0; | |
190 | ||
191 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); | |
192 | return ::new(p) T(arg1, arg2, arg3, arg4, arg5); | |
193 | } | |
194 | ||
195 | namespace Internal { | |
196 | ||
197 | // We define a union of pointer to an integer and pointer to T. | |
198 | // When non-POD arrays are allocated we add a few leading bytes to tell what | |
199 | // the size of the array is. We return to the user the pointer to T. | |
200 | // The way to think of it is as if we allocate a struct like so: | |
201 | // struct Array { | |
202 | // AllocAlignmentInteger m_size; | |
203 | // T m_T[array count]; | |
204 | // }; | |
205 | ||
206 | template <typename T> | |
207 | union ArraySize { | |
208 | AllocAlignmentInteger* size; | |
209 | T* t; | |
210 | }; | |
211 | ||
212 | // This is a support template for fastNewArray. | |
213 | // This handles the case wherein T has a trivial ctor and a trivial dtor. | |
214 | template <typename T, bool trivialCtor, bool trivialDtor> | |
215 | struct NewArrayImpl { | |
216 | static T* fastNewArray(size_t count) | |
217 | { | |
218 | T* p = static_cast<T*>(fastMalloc(sizeof(T) * count)); | |
219 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); | |
220 | return p; | |
221 | } | |
222 | }; | |
223 | ||
224 | // This is a support template for fastNewArray. | |
225 | // This handles the case wherein T has a non-trivial ctor and a trivial dtor. | |
226 | template <typename T> | |
227 | struct NewArrayImpl<T, false, true> { | |
228 | static T* fastNewArray(size_t count) | |
229 | { | |
230 | T* p = static_cast<T*>(fastMalloc(sizeof(T) * count)); | |
231 | ||
232 | if (!p) | |
233 | return 0; | |
234 | ||
235 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); | |
236 | ||
237 | for (T* pObject = p, *pObjectEnd = pObject + count; pObject != pObjectEnd; ++pObject) | |
238 | ::new(pObject) T; | |
239 | ||
240 | return p; | |
241 | } | |
242 | }; | |
243 | ||
244 | // This is a support template for fastNewArray. | |
245 | // This handles the case wherein T has a trivial ctor and a non-trivial dtor. | |
246 | template <typename T> | |
247 | struct NewArrayImpl<T, true, false> { | |
248 | static T* fastNewArray(size_t count) | |
249 | { | |
250 | void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count)); | |
251 | ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) }; | |
252 | ||
253 | if (!p) | |
254 | return 0; | |
255 | ||
256 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); | |
257 | *a.size++ = count; | |
258 | // No need to construct the objects in this case. | |
259 | ||
260 | return a.t; | |
261 | } | |
262 | }; | |
263 | ||
264 | // This is a support template for fastNewArray. | |
265 | // This handles the case wherein T has a non-trivial ctor and a non-trivial dtor. | |
266 | template <typename T> | |
267 | struct NewArrayImpl<T, false, false> { | |
268 | static T* fastNewArray(size_t count) | |
269 | { | |
270 | void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count)); | |
271 | ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) }; | |
272 | ||
273 | if (!p) | |
274 | return 0; | |
275 | ||
276 | fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); | |
277 | *a.size++ = count; | |
278 | ||
279 | for (T* pT = a.t, *pTEnd = pT + count; pT != pTEnd; ++pT) | |
280 | ::new(pT) T; | |
281 | ||
282 | return a.t; | |
283 | } | |
284 | }; | |
285 | } // namespace Internal | |
286 | ||
287 | template <typename T> | |
288 | inline T* fastNewArray(size_t count) | |
289 | { | |
290 | return Internal::NewArrayImpl<T, WTF::HasTrivialConstructor<T>::value, WTF::HasTrivialDestructor<T>::value>::fastNewArray(count); | |
291 | } | |
292 | ||
293 | template <typename T> | |
294 | inline void fastDelete(T* p) | |
295 | { | |
296 | if (!p) | |
297 | return; | |
298 | ||
299 | fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); | |
300 | p->~T(); | |
301 | fastFree(p); | |
302 | } | |
303 | ||
f9bf01c6 A |
304 | template <typename T> |
305 | inline void fastDeleteSkippingDestructor(T* p) | |
306 | { | |
307 | if (!p) | |
308 | return; | |
309 | ||
310 | fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); | |
311 | fastFree(p); | |
312 | } | |
313 | ||
ba379fdc A |
314 | namespace Internal { |
315 | // This is a support template for fastDeleteArray. | |
316 | // This handles the case wherein T has a trivial dtor. | |
317 | template <typename T, bool trivialDtor> | |
318 | struct DeleteArrayImpl { | |
319 | static void fastDeleteArray(void* p) | |
320 | { | |
321 | // No need to destruct the objects in this case. | |
322 | // We expect that fastFree checks for null. | |
323 | fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray); | |
324 | fastFree(p); | |
325 | } | |
326 | }; | |
327 | ||
328 | // This is a support template for fastDeleteArray. | |
329 | // This handles the case wherein T has a non-trivial dtor. | |
330 | template <typename T> | |
331 | struct DeleteArrayImpl<T, false> { | |
332 | static void fastDeleteArray(T* p) | |
333 | { | |
334 | if (!p) | |
335 | return; | |
336 | ||
337 | ArraySize<T> a; | |
338 | a.t = p; | |
339 | a.size--; // Decrement size pointer | |
340 | ||
341 | T* pEnd = p + *a.size; | |
342 | while (pEnd-- != p) | |
343 | pEnd->~T(); | |
344 | ||
345 | fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray); | |
346 | fastFree(a.size); | |
347 | } | |
348 | }; | |
349 | ||
350 | } // namespace Internal | |
351 | ||
352 | template <typename T> | |
353 | void fastDeleteArray(T* p) | |
354 | { | |
355 | Internal::DeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastDeleteArray(p); | |
356 | } | |
357 | ||
358 | ||
359 | template <typename T> | |
360 | inline void fastNonNullDelete(T* p) | |
361 | { | |
362 | fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); | |
363 | p->~T(); | |
364 | fastFree(p); | |
365 | } | |
366 | ||
367 | namespace Internal { | |
368 | // This is a support template for fastDeleteArray. | |
369 | // This handles the case wherein T has a trivial dtor. | |
370 | template <typename T, bool trivialDtor> | |
371 | struct NonNullDeleteArrayImpl { | |
372 | static void fastNonNullDeleteArray(void* p) | |
373 | { | |
374 | fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray); | |
375 | // No need to destruct the objects in this case. | |
376 | fastFree(p); | |
377 | } | |
378 | }; | |
379 | ||
380 | // This is a support template for fastDeleteArray. | |
381 | // This handles the case wherein T has a non-trivial dtor. | |
382 | template <typename T> | |
383 | struct NonNullDeleteArrayImpl<T, false> { | |
384 | static void fastNonNullDeleteArray(T* p) | |
385 | { | |
386 | ArraySize<T> a; | |
387 | a.t = p; | |
388 | a.size--; | |
389 | ||
390 | T* pEnd = p + *a.size; | |
391 | while (pEnd-- != p) | |
392 | pEnd->~T(); | |
393 | ||
394 | fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray); | |
395 | fastFree(a.size); | |
396 | } | |
397 | }; | |
398 | ||
399 | } // namespace Internal | |
400 | ||
401 | template <typename T> | |
402 | void fastNonNullDeleteArray(T* p) | |
403 | { | |
404 | Internal::NonNullDeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastNonNullDeleteArray(p); | |
405 | } | |
406 | ||
407 | ||
408 | } // namespace WTF | |
409 | ||
ba379fdc | 410 | using WTF::FastAllocBase; |
f9bf01c6 | 411 | using WTF::fastDeleteSkippingDestructor; |
ba379fdc A |
412 | |
413 | #endif // FastAllocBase_h |